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

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

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

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

code.sourceCode > span { display: inline; }
</style>
  <link href="data:image/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />
  
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<div class="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center">Safe C++</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3390R0</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2024-09-11</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>
      SG23<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Sean Baxter<br>&lt;<a href="mailto:seanbax.circle@gmail.com" class="email">seanbax.circle@gmail.com</a>&gt;<br>
      Christian Mazakas<br>&lt;<a href="mailto:christian.mazakas@gmail.com" class="email">christian.mazakas@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>
<ul>
<li><a href="#the-call-for-memory-safety" id="toc-the-call-for-memory-safety"><span class="toc-section-number">1.1</span> The call for memory
safety<span></span></a></li>
<li><a href="#extend-c-for-safety" id="toc-extend-c-for-safety"><span class="toc-section-number">1.2</span> Extend C++ for
safety<span></span></a></li>
<li><a href="#a-safe-program" id="toc-a-safe-program"><span class="toc-section-number">1.3</span> A safe
program<span></span></a></li>
<li><a href="#memory-safety-as-terms-and-conditions" id="toc-memory-safety-as-terms-and-conditions"><span class="toc-section-number">1.4</span> Memory safety as terms and
conditions<span></span></a></li>
<li><a href="#categories-of-safety" id="toc-categories-of-safety"><span class="toc-section-number">1.5</span> Categories of
safety<span></span></a></li>
</ul></li>
<li><a href="#design-overview" id="toc-design-overview"><span class="toc-section-number">2</span> Design overview<span></span></a>
<ul>
<li><a href="#the-safe-context" id="toc-the-safe-context"><span class="toc-section-number">2.1</span> The
<code class="sourceCode cpp">safe</code> context<span></span></a></li>
<li><a href="#borrow-checking" id="toc-borrow-checking"><span class="toc-section-number">2.2</span> Borrow
checking<span></span></a></li>
<li><a href="#explicit-mutation" id="toc-explicit-mutation"><span class="toc-section-number">2.3</span> Explicit
mutation<span></span></a></li>
<li><a href="#relocation-object-model" id="toc-relocation-object-model"><span class="toc-section-number">2.4</span> Relocation object
model<span></span></a></li>
<li><a href="#choice-types" id="toc-choice-types"><span class="toc-section-number">2.5</span> Choice types<span></span></a></li>
<li><a href="#interior-mutability" id="toc-interior-mutability"><span class="toc-section-number">2.6</span> Interior
mutability<span></span></a></li>
<li><a href="#send-and-sync" id="toc-send-and-sync"><span class="toc-section-number">2.7</span>
<code class="sourceCode cpp">send</code> and
<code class="sourceCode cpp">sync</code><span></span></a></li>
<li><a href="#unresolved-design-issues" id="toc-unresolved-design-issues"><span class="toc-section-number">2.8</span> Unresolved design
issues<span></span></a></li>
</ul></li>
<li><a href="#implementation-guidance" id="toc-implementation-guidance"><span class="toc-section-number">3</span> Implementation
guidance<span></span></a></li>
<li><a href="#conclusion" id="toc-conclusion"><span class="toc-section-number">4</span> Conclusion<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">5</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" id="introduction"><span class="header-section-number">1</span> Introduction<a href="#introduction" class="self-link"></a></h1>
<h2 data-number="1.1" id="the-call-for-memory-safety"><span class="header-section-number">1.1</span> The call for memory safety<a href="#the-call-for-memory-safety" class="self-link"></a></h2>
<p>Over the past two years, the United States Government has been
issuing warnings about memory-unsafe programming languages with
increasing urgency. Much of the country’s critical infrastructure relies
on software written in C and C++, languages which are very memory
<em>unsafe</em>, leaving these systems more vulnerable to exploits by
adversaries.</p>
<ul>
<li><p>Nov. 10, 2022 - <strong>NSA Releases Guidance on How to Protect
Against Software Memory Safety Issues</strong><span class="citation" data-cites="nsa-guidance">[<a href="https://www.nsa.gov/Press-Room/News-Highlights/Article/Article/3215760/nsa-releases-guidance-on-how-to-protect-against-software-memory-safety-issues/" role="doc-biblioref">nsa-guidance</a>]</span></p></li>
<li><p>Sep. 20, 2023 - <strong>The Urgent Need for Memory Safety in
Software Products</strong><span class="citation" data-cites="cisa-urgent">[<a href="https://www.cisa.gov/news-events/news/urgent-need-memory-safety-software-products" role="doc-biblioref">cisa-urgent</a>]</span></p></li>
<li><p>Dec. 6, 2023 - <strong>CISA Releases Joint Guide for Software
Manufacturers: The Case for Memory Safe Roadmaps</strong><span class="citation" data-cites="cisa-roadmaps">[<a href="https://www.cisa.gov/news-events/alerts/2023/12/06/cisa-releases-joint-guide-software-manufacturers-case-memory-safe-roadmaps" role="doc-biblioref">cisa-roadmaps</a>]</span></p></li>
<li><p>Feb. 26, 2024 - <strong>Future Software Should Be Memory
Safe</strong><span class="citation" data-cites="white-house">[<a href="https://www.whitehouse.gov/oncd/briefing-room/2024/02/26/press-release-technical-report/" role="doc-biblioref">white-house</a>]</span></p></li>
<li><p>May 7, 2024 - <strong>National Cybersecurity Strategy
Implementation Plan</strong><span class="citation" data-cites="ncsi-plan">[<a href="https://www.whitehouse.gov/wp-content/uploads/2024/05/NCSIP-Version-2-FINAL-May-2024.pdf" role="doc-biblioref">ncsi-plan</a>]</span></p></li>
</ul>
<p>The government papers are backed by industry research. Microsoft’s
bug telemetry reveals that 70% of its vulnerabilities would be stopped
by memory safe languages.<span class="citation" data-cites="ms-vulnerabilities">[<a href="https://msrc.microsoft.com/blog/2019/07/we-need-a-safer-systems-programming-language" role="doc-biblioref">ms-vulnerabilities</a>]</span> Google’s research
finds 68% of 0day exploits are related to memory corruption.<span class="citation" data-cites="google-0day">[<a href="https://googleprojectzero.blogspot.com/p/0day.html" role="doc-biblioref">google-0day</a>]</span></p>
<ul>
<li>Mar. 4, 2024 - <strong>Secure by Design: Google’s Perspective on
Memory Safety</strong><span class="citation" data-cites="secure-by-design">[<a href="https://research.google/pubs/secure-by-design-googles-perspective-on-memory-safety/" role="doc-biblioref">secure-by-design</a>]</span></li>
</ul>
<p>Security professionals urge projects to migrate away from C++ and
adopt memory safe languages. But the scale of the problem is daunting.
C++ powers software that has generated trillions of dollars of value.
There are many veteran C++ programmers and lots of C++ code. Given how
wide-spread C++ is, what can industry really do to improve software
quality and reduce vulnerabilities? What are the options for introducing
new memory safe code into existing projects and hardening software that
already exists?</p>
<p>There’s only one popular systems level/non-garbage collected language
that provides rigorous memory safety. That’s the Rust language.<span class="citation" data-cites="rust-language">[<a href="https://doc.rust-lang.org/book/" role="doc-biblioref">rust-language</a>]</span> Although they play in the
same space, C++ and Rust have different designs with limited interop
capability, making incremental migration from C++ to Rust a painstaking
process.</p>
<p>Rust lacks function overloading, templates, inheritance and
exceptions. C++ lacks traits, relocation and borrow checking. These
discrepancies are responsible for an impedence mismatch when interfacing
the two languages. Most code generators for inter-language bindings
aren’t able to represent features of one language in terms of the
features of another. They typically identify a small number of special
vocabulary types,<span class="citation" data-cites="vocabulary-types">[<a href="https://cxx.rs/bindings.html" role="doc-biblioref">vocabulary-types</a>]</span> which have first-class
ergonomics, and limit functionality of other constructs.</p>
<p>The foreignness of Rust for career C++ developers combined with the
the friction of interop tools makes hardening C++ applications by
rewriting critical sections in Rust difficult. Why is there no
in-language solution to memory safety? <em>Why not a Safe C++?</em></p>
<h2 data-number="1.2" id="extend-c-for-safety"><span class="header-section-number">1.2</span> Extend C++ for safety<a href="#extend-c-for-safety" class="self-link"></a></h2>
<p>The goal of this proposal is to advance a superset of C++ with a
<em>rigorously safe subset</em>. Begin a new project, or take an
existing one, and start writing safe code in C++. Code in the safe
context exhibits the same strong safety guarantees as code written in
Rust.</p>
<p>Rigorous safety is a carrot-and-stick approach. The stick comes
first. The stick is what security researchers and regulators care about.
Safe C++ developers are prohibited from writing operations that may
result in lifetime safety, type safety or thread safety undefined
behaviors. Sometimes these operations are prohibited by the compiler
frontend, as is the case with pointer arithmetic. Sometimes the
operations are prohibited by static analysis in the compiler’s
middle-end; that stops use of initialized variables and use-after-free
bugs, and it’s the enabling technology of the <em>ownership and
borrowing</em> safety model. The remainder of issues, like out-of-bounds
array subscripts, are addressed with runtime panic and aborts.</p>
<p>The carrot is a suite of new capabilities which improve on the unsafe
ones denied to users. The affine type system makes it easier to relocate
objects without breaking type safety. Pattern matching, which is safe
and expressive, interfaces with the extension’s new choice types. Borrow
checking,<span class="citation" data-cites="borrow-checking">[<a href="https://rust-lang.github.io/rfcs/2094-nll.html" role="doc-biblioref">borrow-checking</a>]</span> the most sophisticated
part of the Safe C++, provides a new reference type that flags
use-after-free and iterator invalidation defects at compile time.</p>
<p>What are the properties we’re trying to deliver with Safe C++?</p>
<ul>
<li>A superset of C++ with a <em>safe subset</em>. Undefined behavior is
prohibited from originating in the safe subset.</li>
<li>The safe and unsafe parts of the language are clearly delineated.
Users must explicitly leave the safe context to write unsafe
operations.</li>
<li>The safe subset must remain <em>useful</em>. If we get rid of a
crucial unsafe technology, like unions and pointers, we should supply a
safe alternative, like choice types and borrows. A safe toolchain is not
useful if it’s so inexpressive that you can’t get your work done.</li>
<li>The new system can’t break existing code. If you point a Safe C++
compiler at existing C++ code, that code must compile normally. Users
opt into the new safety mechanisms. Safe C++ is an extension of C++. It
adds a robust safety model, but it’s not a new language.</li>
</ul>
<h2 data-number="1.3" id="a-safe-program"><span class="header-section-number">1.3</span> A safe program<a href="#a-safe-program" class="self-link"></a></h2>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/iterator.cxx"><strong>iterator.cxx</strong></a>
– <a href="https://godbolt.org/z/vneosEGrK">(Compiler Explorer)</a></p>
<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="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;std2.h&gt;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  std2<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> vec <span class="op">{</span> <span class="dv">11</span>, <span class="dv">15</span>, <span class="dv">20</span> <span class="op">}</span>;</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span><span class="op">(</span><span class="dt">int</span> x <span class="op">:</span> vec<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Ill-formed. mutate of vec invalidates iterator in ranged-for.</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span><span class="op">(</span>x <span class="op">%</span> <span class="dv">2</span><span class="op">)</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>      mut vec<span class="op">.</span>push_back<span class="op">(</span>x<span class="op">)</span>;</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    std2<span class="op">::</span>println<span class="op">(</span>x<span class="op">)</span>;</span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb1"><pre class="sourceCode txt"><code class="sourceCode default"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>$ circle iterator.cxx -I ../libsafecxx/single-header/</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>safety: during safety checking of int main() safe</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  borrow checking: iterator.cxx:10:11</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>        mut vec.push_back(x);</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>            ^</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>  mutable borrow of vec between its shared borrow and its use</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>  loan created at iterator.cxx:7:15</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    for(int x : vec) {</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>                ^</span></code></pre></div>
<p>Consider this demonstration of Safe C++ that catches iterator
invalidation, a kind of use-after-free bug. Let’s break it down line by
line:</p>
<p>Line 1: <code class="sourceCode cpp"><span class="pp">#</span><span class="er">feature on safety</span></code>
- Activate the safety-related keywords within this file. Other files in
your translation unit are unaffected. This is how Safe C++ avoids
breaking existing code–everything is opt-in, including the new keywords
and syntax. The <code class="sourceCode cpp"><span class="op">[</span>safety<span class="op">]</span></code>
feature changes the object model for function definitions, enabling
object relocation and deferred initialization. It lowers function
definitions to mid-level intermediate representation (MIR),<span class="citation" data-cites="mir">[<a href="https://rustc-dev-guide.rust-lang.org/mir/index.html" role="doc-biblioref">mir</a>]</span> on which borrow checking is
performed to flag use-after-free bugs on checked references.</p>
<p>Line 2: <code class="sourceCode cpp"><span class="pp">#include </span><span class="im">&lt;std2.h&gt;</span></code>
- Include the new safe containers and algorithms. Safety hardening is
about reducing your exposure to unsafe APIs. The current Standard
Library is full of unsafe APIs. The safe standard library in namespace
<code class="sourceCode cpp">std2</code> will provide the same basic
functionality, but with containers that are lifetime-aware and type
safe.</p>
<p>Line 4: <code class="sourceCode cpp"><span class="dt">int</span> main<span class="op">()</span> safe</code>
- The new <em>safe-specifier</em> is part of a function’s type, just
like <em>noexcept-specifier</em>.
<code class="sourceCode cpp">main</code>’s definition starts in a safe
context. Unsafe operations such as pointer dereferences, which may raise
undefined behavior, are disallowed. Rust’s functions are safe by
default. C++’s are unsafe by default. But that’s now just a syntax
difference. Once you enter a <a href="#the-safe-context">safe
context</a> in C++ by using the <em>safe-specifier</em>, you’re backed
by the same rigorous safety guarantees that Rust provides.</p>
<p>Line 5: <code class="sourceCode cpp">std2<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> vec <span class="op">{</span> <span class="dv">11</span>, <span class="dv">15</span>, <span class="dv">20</span> <span class="op">}</span>;</code>
- List initialization of a memory-safe vector. This vector is aware of
lifetime parameters, so borrow checking would extend to element types
that have lifetimes. The vector’s constructor doesn’t use <code class="sourceCode cpp">std<span class="op">::</span>initializer_list<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span></code>.
That type is problematic for two reasons: first, users are given
pointers into the argument data, and reading from pointers is unsafe;
second, the <code class="sourceCode cpp">std<span class="op">::</span>initializer_list</code>
<em>doesn’t own</em> its data, making relocation impossible. For these
reasons, Safe C++ introduces a <a href="#initializer-lists"><code class="sourceCode cpp">std2<span class="op">::</span>initializer_list</code></a>,
which supports our ownership object model.</p>
<p>Line 7: <code class="sourceCode cpp"><span class="cf">for</span><span class="op">(</span><span class="dt">int</span> x <span class="op">:</span> vec<span class="op">)</span></code>
- Ranged-for on the vector. The standard mechanism returns a pair of
iterators, which are pointers wrapped in classes. C++ iterators are
unsafe. They come in begin and end pairs, and don’t share common
lifetime parameters, making borrow checking them impractical. The Safe
C++ version uses slice iterators, which resemble Rust’s
<code class="sourceCode cpp">Iterator</code>.<span class="citation" data-cites="rust-iterator">[<a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html" role="doc-biblioref">rust-iterator</a>]</span> These safe iterators are
implemented with lifetime parameters, making them robust against
iterator invalidation defects.</p>
<p>Line 10: <code class="sourceCode cpp">mut vec<span class="op">.</span>push_back<span class="op">(</span>x<span class="op">)</span>;</code>
- Push a value onto the vector. The
<code class="sourceCode cpp">mut</code> token establishes a <a href="#the-mutable-context"><em>mutable context</em></a> which enables
standard conversions from lvalues to mutable borrows and references.
When <code class="sourceCode cpp"><span class="op">[</span>safety<span class="op">]</span></code>
is enabled, <em>all mutations are explicit</em>. Explicit mutation lends
precision when choosing between shared borrows and mutable borrows of an
object. Rust doesn’t feature function overloading, so it will bind
whatever kind of reference it needs to a member function’s object. C++,
by contrast, has function overloading, so we’ll need to be explicit in
order to get the overload we want. Use
<code class="sourceCode cpp">mut</code> to bind mutable borrows. Or
don’t use it and bind shared borrows.</p>
<p>If <code class="sourceCode cpp">main</code> checks out syntatically,
its AST is lowered to MIR, where initialization and borrow checking
takes place. The hidden
<code class="sourceCode cpp">slice_iterator</code> that powers the
ranged-for loop stays initialized over the duration of the loop. The
<code class="sourceCode cpp">push_back</code> call <em>invalidates</em>
that iterator, by mutating a place (the vector) that the iterator has a
constraint on. When the value <code class="sourceCode cpp">x</code> is
next loaded out of the iterator, the borrow checker raises an error:
<code class="sourceCode cpp"><span class="kw">mutable</span> borrow of vec between its shared borrow <span class="kw">and</span> its use</code>.
The borrow checker prevents Safe C++ from compiling a program that may
exhibit undefined behavior. This analysis is done at compile time. It
has no impact on your binary’s size or execution speed.</p>
<p>This sample is only a few lines, but it introduces several new
mechanisms and types. A comprehensive effort is needed to supply a
superset of the language with a safe subset that has enough flexibility
to remain expressive.</p>
<h2 data-number="1.4" id="memory-safety-as-terms-and-conditions"><span class="header-section-number">1.4</span> Memory safety as terms and
conditions<a href="#memory-safety-as-terms-and-conditions" class="self-link"></a></h2>
<p>Memory safe languages are predicated on a basic observation of
programmer behavior: developers will try to use a library and only read
documentation if their first few attempts don’t seem to work. This is
dangerous for software correctness, since seeming to work is not the
same as working.</p>
<p>Many C++ functions have preconditions that you’d have to read the
docs to understand. Violating preconditions, which is possible with
benign-looking usage, could cause undefined behavior and open your
software to attack. <em>Software safety and security should not be
predicated on programmers following documentation.</em></p>
<p>Here’s the memory safety value proposition: language and library
vendors make an extra effort to provide a robust environment so that
users <em>don’t have to read the docs</em>. No matter how they use the
tooling, their actions will not raise undefined behavior and compromise
their software to safety-related exploits. No system can guard against
all misuse, and hastily written code may have plenty of logic bugs. But
those logic bugs won’t lead to memory-safety vulnerabilities.</p>
<p>Consider an old libc function,
<code class="sourceCode cpp">std<span class="op">::</span>isprint</code>,<span class="citation" data-cites="isprint">[<a href="https://en.cppreference.com/w/cpp/string/byte/isprint" role="doc-biblioref">isprint</a>]</span> that exhibits unsafe design.
This function takes an
<code class="sourceCode cpp"><span class="dt">int</span></code>
parameter. <em>But it’s not valid to call
<code class="sourceCode cpp">std<span class="op">::</span>isprint</code>
for all int arguments</em>. The preconditions state the function be
called only with arguments between -1 and 255:</p>
<blockquote>
<p>Like all other functions from <code class="sourceCode cpp"><span class="op">&lt;</span>cctype<span class="op">&gt;</span></code>,
the behavior of
<code class="sourceCode cpp">std<span class="op">::</span>isprint</code>
is undefined if the argument’s value is neither representable as
unsigned char nor equal to EOF. To use these functions safely with plain
chars (or signed chars), the argument should first be converted to
unsigned char. Similarly, they should not be directly used with standard
algorithms when the iterator’s value type is char or signed char.
Instead, convert the value to unsigned char first.</p>
</blockquote>
<p>It feels only right, in the year 2024, to pass Unicode code points to
functions that are typed with
<code class="sourceCode cpp"><span class="dt">int</span></code> and deal
with characters. But doing so may crash your application, or worse.
While the mistake is the caller’s for not reading the documentation and
obeying the preconditions, it’s fair to blame the design of the API. The
safe context provided by memory safe languages prevents usage or
authoring of functions like
<code class="sourceCode cpp">std<span class="op">::</span>isprint</code>
which exhibit undefined behavior when called with invalid arguments.</p>
<p>Rust’s approach to safety<span class="citation" data-cites="safe-unsafe-meaning">[<a href="https://doc.rust-lang.org/nomicon/safe-unsafe-meaning.html" role="doc-biblioref">safe-unsafe-meaning</a>]</span> centers on defining
responsibility for enforcing preconditions. In a safe context, the user
can call safe functions without compromising program soundness. Failure
to read the docs may risk correctness, but it won’t risk undefined
behavior. When the user wants to call an unsafe function from a safe
context, they <em>explicitly take responsibility</em> for sound usage of
that unsafe function. The user writes the
<code class="sourceCode cpp">unsafe</code> token as a kind of contract:
the user has read the terms and conditions of the unsafe function and
affirms that it’s not being used in a way that violates its
preconditions.</p>
<p>Who is to blame when undefined behavior is detected–the caller or the
callee? Standard C++ does not address this. But Rust’s safety model
does: whoever typed out the <code class="sourceCode cpp">unsafe</code>
token is to blame. Safe C++ adopts the same principle. Code is divided
into unsafe and safe contexts. Unsafe operations may only occur in
unsafe contexts. Dropping from a safe context to an unsafe context
requires use of the <code class="sourceCode cpp">unsafe</code> keyword.
This leaves an artifact that makes for easy audits: reviewers search for
the <code class="sourceCode cpp">unsafe</code> keyword and focus their
attention there first. Developers checking code into Rust’s standard
library are even required to write <em>safety comments</em><span class="citation" data-cites="safety-comments">[<a href="https://std-dev-guide.rust-lang.org/policy/safety-comments.html" role="doc-biblioref">safety-comments</a>]</span> before every unsafe
block, indicating proper usage and explaining why it’s sound.</p>
<p>Consider the design of a future <code class="sourceCode cpp">std2<span class="op">::</span>isprint</code>
function. If it’s marked <code class="sourceCode cpp">safe</code>, it
must be sound for all argument values. If it’s called with an argument
that is out of its supported range, it must fail in a deterministic way:
it could return an error code, it could throw an exception or it could
panic and abort. Inside the <code class="sourceCode cpp">std2<span class="op">::</span>isprint</code>
implementation, there’s probably a lookup table with capabilities for
each supported character. If the lookup table is accessed with a slice,
an out-of-bounds access will implicitly generate a bounds check and
panic and abort on failure. If the lookup table is accessed through a
pointer, the implementer tests the subscript against the capacity of the
lookup table and fails if it’s out-of-range. Having enforced the
preconditions, they write the <code class="sourceCode cpp">unsafe</code>
keyword to drop to the unsafe context and fetch the data from the
pointer. The <code class="sourceCode cpp">unsafe</code> keyword is the
programmer’s oath that the subsequent unsafe operations are sound.</p>
<p>In ISO C++, soundness bugs often occur because caller and callee
don’t know who should enforce preconditions, so neither of them do. In
Safe C++, there’s a convention backed up by the compiler, eliminating
this confusion and improving software quality.</p>
<h2 data-number="1.5" id="categories-of-safety"><span class="header-section-number">1.5</span> Categories of safety<a href="#categories-of-safety" class="self-link"></a></h2>
<p>It’s instructive to break the memory safety problem down into four
categories. Each of these is addressed with a different language
technology.</p>
<h3 data-number="1.5.1" id="lifetime-safety"><span class="header-section-number">1.5.1</span> Lifetime safety<a href="#lifetime-safety" class="self-link"></a></h3>
<p>How do we ensure that dangling references are never used? There are
two mainstream lifetime safety technologies: garbage collection and
borrow checking. Garbage collection is simple to implement and use, but
moves object allocations to the heap, making it incompatible with manual
memory manegement. It keeps objects initialized as long as there are
live references to them, making it incompatible with C++’s RAII<span class="citation" data-cites="raii">[<a href="https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization" role="doc-biblioref">raii</a>]</span> object model.</p>
<p>Borrow checking is an advanced form of live analysis. It keeps track
of the <em>live references</em> at every point in the function, and
errors when there’s a <em>conflicting action</em> on a place associated
with a live reference. For example, writing to, moving or dropping an
object with a live shared borrow will raise a borrow check error.
Pushing to a vector with a live iterator will raise an iterator
invalidation error. This technology is compatible with manual memory
management and RAII, making it a good fit for C++.</p>
<p>Borrow checking is a kind of local analysis. It avoids whole-program
analysis by enforcing the <em>law of exclusivity</em>. Checked
references (borrows) come in two flavors: mutable and shared, spelled
<code class="sourceCode cpp">T<span class="op">^</span></code> and <code class="sourceCode cpp"><span class="kw">const</span> T<span class="op">^</span></code>,
respectively. There can be one live mutable reference to a place, or any
number of shared references to a place, but not both at once. Upholding
this principle makes it easier to reason about your program. Since the
law of exclusivity prohibits mutable aliasing, if a function is passed a
mutable reference and some shared references, you can be certain that
the function won’t have side effects that, through the mutable
reference, cause the invalidation of those shared references.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/string_view.cxx"><strong>string_view.cxx</strong></a>
– <a href="https://godbolt.org/z/8KabhKP97">(Compiler Explorer)</a></p>
<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="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;std2.h&gt;</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> <span class="kw">namespace</span> std2;</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Populate the vector with views with a nice mixture of lifetimes.</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>  vector<span class="op">&lt;</span>string_view<span class="op">&gt;</span> views <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">// string_view with /static lifetime.</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>  mut views<span class="op">.</span>push_back<span class="op">(</span><span class="st">&quot;From a string literal&quot;</span><span class="op">)</span>;</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>  <span class="co">// string_view with outer scope lifetime.</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>  string s1<span class="op">(</span><span class="st">&quot;From string object 1&quot;</span><span class="op">)</span>;</span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>  mut views<span class="op">.</span>push_back<span class="op">(</span>s1<span class="op">)</span>;</span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>    <span class="co">// string_view with inner scope lifetime.</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>    string s2<span class="op">(</span><span class="st">&quot;From string object 2&quot;</span><span class="op">)</span>;</span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>    mut views<span class="op">.</span>push_back<span class="op">(</span>s2<span class="op">)</span>;</span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a>    <span class="co">// s2 goes out of scope. views now holds dangling pointers into</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a>    <span class="co">// out-of-scope data.</span></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Print the strings. s2 already fell out of scope, so this should</span></span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a>  <span class="co">// be a borrowck violation. `views` now contains objects that hold</span></span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a>  <span class="co">// dangling pointers.</span></span>
<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a>  println<span class="op">(</span><span class="st">&quot;Printing from the outer scope:&quot;</span><span class="op">)</span>;</span>
<span id="cb2-30"><a href="#cb2-30" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span><span class="op">(</span>string_view sv <span class="op">:</span> views<span class="op">)</span></span>
<span id="cb2-31"><a href="#cb2-31" aria-hidden="true" tabindex="-1"></a>    println<span class="op">(</span>sv<span class="op">)</span>;</span>
<span id="cb2-32"><a href="#cb2-32" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb3"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>$ circle string_view.cxx -I ../libsafecxx/single-header/</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>safety: during safety checking of int main() safe</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>  borrow checking: string_view.cxx:30:24</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    for(string_view sv : views) </span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>                         ^</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>  use of views depends on expired loan</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>  drop of s2 between its shared borrow and its use</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>  s2 declared at string_view.cxx:19:12</span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>      string s2(&quot;From string object 2&quot;); </span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>             ^</span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>  loan created at string_view.cxx:20:25</span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>      mut views.push_back(s2); </span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>                          ^</span></code></pre></div>
<p>Borrow checking provides bullet-proof guarantees against lifetime
safety defects when dealing with collections of references or views into
objects with different scopes. Take a vector of <code class="sourceCode cpp">std2<span class="op">::</span>string_view</code>.
This string view is special. It’s defined with a lifetime parameter that
establishes a lifetime constraint on the string into which it points:
that string must be in scope for all uses of the view.</p>
<p>Load the vector up with views into three different strings: a string
constant with <code class="sourceCode cpp"><span class="op">/</span><span class="kw">static</span></code>
lifetime, a string in an outer scope and a string in an inner scope.
Printing the contents of the vector from the outer scope raises a borrow
checker error, because one of the function’s lifetime constraints is
violated: the vector depends on a loan on
<code class="sourceCode cpp">s2</code>, which is out-of-scope at the
point of use.</p>
<p>Garbage collection solves this problem in a different way:
<code class="sourceCode cpp">s1</code> and
<code class="sourceCode cpp">s2</code> are stored on the GC-managed
heap, and they’re kept in scope as long as there are live references to
them. That’s an effective system, but it’s not the right choice for C++,
where deterministic destruction order is core to the language’s
design.</p>
<h3 data-number="1.5.2" id="type-safety"><span class="header-section-number">1.5.2</span> Type safety<a href="#type-safety" class="self-link"></a></h3>
<blockquote>
<p>I call it my billion-dollar mistake. It was the invention of the null
reference in 1965. At that time, I was designing the first comprehensive
type system for references in an object oriented language (ALGOL W). My
goal was to ensure that all use of references should be absolutely safe,
with checking performed automatically by the compiler. But I couldn’t
resist the temptation to put in a null reference, simply because it was
so easy to implement. This has led to innumerable errors,
vulnerabilities, and system crashes, which have probably caused a
billion dollars of pain and damage in the last forty years.</p>
<p>– <cite>Tony Hoare</cite><span class="citation" data-cites="hoare">[<a href="https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/" role="doc-biblioref">hoare</a>]</span></p>
</blockquote>
<p>The “billion-dollar mistake” is a type safety problem. Consider <code class="sourceCode cpp">std<span class="op">::</span>unique_ptr</code>.
It has two states: engaged and disengaged. The class presents member
functions like <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">*</span></code>
and <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">-&gt;</span></code>
that are valid when the object is in the engaged state and
<em>undefined</em> when the object is disengaged.
<code class="sourceCode cpp"><span class="op">-&gt;</span></code> is the
most important API for smart pointers. Calling it when the pointer is
null? That’s your billion-dollar mistake.</p>
<p>As Hoare observes, the problem comes from conflating two different
things, a pointer to an object and an empty state, into the same type
and giving them the same interface. Smart pointers should only hold
valid pointers. Denying the null state eliminates undefined
behavior.</p>
<p>We address the type safety problem by overhauling the object model.
Safe C++ features a new kind of move: <a href="#relocation-object-model"><em>relocation</em></a>, also called
<em>destructive move</em>. The object model is called an <em>affine</em>
or a <em>linear</em> type system. Unless explicitly initialized, objects
start out <em>uninitialized</em>. They can’t be used in this state. When
you assign to an object, it becomes initialized. When you relocate from
an object, it’s value is moved and it’s reset to uninitialized. If you
relocate from an object inside control flow, it becomes <em>potentially
uninitialized</em>, and its destructor is conditionally executed after
reading a compiler-generated drop flag.</p>
<p><code class="sourceCode cpp">std2<span class="op">::</span>box</code>
is our version of <code class="sourceCode cpp">unique_ptr</code>. It has
no null state. There’s no default constructor. Dereference it without
risk of undefined behavior. If this design is so much safer, why doesn’t
C++ simply introduce its own fixed
<code class="sourceCode cpp">unique_ptr</code> without a null state?
Blame C++11 move semantics.</p>
<p>How do you move objects around in C++? Use
<code class="sourceCode cpp">std<span class="op">::</span>move</code> to
select the move constructor. That moves data out of the old object,
leaving it in a default state. For smart pointers, that’s the null
state. If <code class="sourceCode cpp">unique_ptr</code> didn’t have a
null state, it couldn’t be moved in C++. This affine type system
implements moves with relocation. That’s type safe. Standard C++’s
object model implements moves with move construction. That’s unsafe.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/box.cxx"><strong>box.cxx</strong></a>
– <a href="https://godbolt.org/z/aYvqoTv51">(Compiler Explorer)</a></p>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;std2.h&gt;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// p is uninitialized.</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>  std2<span class="op">::</span>box<span class="op">&lt;</span>std2<span class="op">::</span>string_view<span class="op">&gt;</span> p;</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Error: p is uninitialized.</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>  println<span class="op">(*</span>p<span class="op">)</span>;</span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>  <span class="co">// p is definitely initialized.</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>  p <span class="op">=</span> std2<span class="op">::</span>box<span class="op">&lt;</span>std2<span class="op">::</span>string_view<span class="op">&gt;(</span><span class="st">&quot;Hello Safety&quot;</span><span class="op">)</span>;</span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Ok.</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>  println<span class="op">(*</span>p<span class="op">)</span>;</span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>  <span class="co">// p is moved into q. Now p is uninitialized again.</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> q <span class="op">=</span> rel p;</span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Error: p is uninitialized.</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a>  println<span class="op">(*</span>p<span class="op">)</span>;</span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb5"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>$ circle box.cxx -I ../libsafecxx/single-header/</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>safety: during safety checking of int main() safe</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>  initialization analysis: box.cxx:9:12</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    println(*p);</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>             ^</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>  cannot use uninitialized object p with type std2::box&lt;std2::string_view&gt;</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>  initialization analysis: box.cxx:21:12</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>    println(*p);</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>             ^</span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>  cannot use uninitialized object p with type std2::box&lt;std2::string_view&gt;</span></code></pre></div>
<p>The <em>rel-expression</em> names an object or subobject and
relocates that into a new value. The old object becomes uninitialized.
Using an uninitialized object generates a compiler error. Contrast the
legacy object model with the relocation model: using a null <code class="sourceCode cpp">std<span class="op">::</span>unique_ptr</code>
results in runtime undefined behavior, but using an uninitialized
<code class="sourceCode cpp">std2<span class="op">::</span>box</code>
raises a compile-time error.</p>
<p>We have to reimagine our standard library in the presence of
relocation. Most kinds of resource handles include null states. These
should all be replaced by safe versions to reduce exposure to unsafe
APIs.</p>
<p>The compiler can only relocate local variables. How do we move
objects that live on the heap, or for which we only have a pointer or
reference? We need to use optional types.</p>
<p>The C++ Standard Library has an optional type, but it’s not safe to
use. The optional API is full of undefined behaviors: using <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">*</span></code>
or <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">-&gt;</span></code>
while the value is disengaged raises undefined behavior. <code class="sourceCode cpp">std<span class="op">::</span>expected</code>, new
to C++23, exhibits the same undefined behaviors for out-of-contract uses
of its <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">*</span></code>,
<code class="sourceCode cpp"><span class="kw">operator</span><span class="op">-&gt;</span></code>
and <code class="sourceCode cpp">error</code> APIs.</p>
<p>If we were to represent the null state by wrapping the safe
<code class="sourceCode cpp">std2<span class="op">::</span>box</code> in
an <code class="sourceCode cpp">std<span class="op">::</span>optional</code>,
that would be just as unsafe as using <code class="sourceCode cpp">std<span class="op">::</span>unique_ptr</code>.
The <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">-&gt;</span></code>
is unsafe either way. We need a new <em>sum type</em> that doesn’t
exhibit the union-like safety defects of <code class="sourceCode cpp">std<span class="op">::</span>optional</code> and
<code class="sourceCode cpp">std<span class="op">::</span>expected</code>.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">+&gt;</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>choice optional</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">default</span> none,</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">[[</span><span class="at">safety</span><span class="op">::</span><span class="at">unwrap</span><span class="op">]]</span> some<span class="op">(</span>T<span class="op">)</span>;</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> E<span class="op">&gt;</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>  expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span> ok_or<span class="op">(</span>self, E e<span class="op">)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> match<span class="op">(</span>self<span class="op">)</span> <span class="op">-&gt;</span> expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>      <span class="op">.</span>some<span class="op">(</span>t<span class="op">)</span> <span class="op">=&gt;</span> <span class="op">.</span>ok<span class="op">(</span>rel t<span class="op">)</span>;</span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>      <span class="op">.</span>none    <span class="op">=&gt;</span> <span class="op">.</span>err<span class="op">(</span>rel e<span class="op">)</span>;</span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>  T expect<span class="op">(</span>self, str msg<span class="op">)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> match<span class="op">(</span>self<span class="op">)</span> <span class="op">-&gt;</span> T <span class="op">{</span></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a>      <span class="op">.</span>some<span class="op">(</span>t<span class="op">)</span> <span class="op">=&gt;</span> rel t;</span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a>      <span class="op">.</span>none    <span class="op">=&gt;</span> panic<span class="op">(</span>msg<span class="op">)</span>;</span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a>  T unwrap<span class="op">(</span>self<span class="op">)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> match<span class="op">(</span>self<span class="op">)</span> <span class="op">-&gt;</span> T <span class="op">{</span></span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true" tabindex="-1"></a>      <span class="op">.</span>some<span class="op">(</span>t<span class="op">)</span> <span class="op">=&gt;</span> rel t;</span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true" tabindex="-1"></a>      <span class="op">.</span>none    <span class="op">=&gt;</span> panic<span class="op">(</span><span class="st">&quot;{} is none&quot;</span><span class="op">.</span>format<span class="op">(</span>optional<span class="op">~</span>string<span class="op">))</span>;</span>
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb6-27"><a href="#cb6-27" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb6-28"><a href="#cb6-28" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>The new <code class="sourceCode cpp">std2<span class="op">::</span>optional</code> is
a <a href="#choice-types"><em>choice type</em></a>, a first-class
discriminated union, accessible only with <a href="#pattern-matching"><em>pattern matching</em></a>. Pattern matching
makes type safety violations on choice types impossible: we can’t access
the wrong state of the object.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/match.cxx"><strong>match.cxx</strong></a>
– <a href="https://godbolt.org/z/KbGhKz78v">(Compiler Explorer)</a></p>
<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="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;std2.h&gt;</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>choice Value <span class="op">{</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>  i32<span class="op">(</span><span class="dt">int</span><span class="op">)</span>,</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>  f32<span class="op">(</span><span class="dt">float</span><span class="op">)</span>,</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>  f64<span class="op">(</span><span class="dt">double</span><span class="op">)</span>,</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>  str<span class="op">(</span>std2<span class="op">::</span>string<span class="op">)</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> print<span class="op">(</span>Value val<span class="op">)</span> safe <span class="op">{</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>  match<span class="op">(</span>val<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Type safety bugs are impossible inside the pattern match.</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a>    <span class="co">// The alternatives listed must be exhaustive.</span></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span>i32<span class="op">(</span>i32<span class="op">)</span> <span class="op">=&gt;</span> std2<span class="op">::</span>println<span class="op">(</span>i32<span class="op">)</span>;</span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span>f32<span class="op">(</span>f32<span class="op">)</span> <span class="op">=&gt;</span> std2<span class="op">::</span>println<span class="op">(</span>f32<span class="op">)</span>;</span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span>f64<span class="op">(</span>f64<span class="op">)</span> <span class="op">=&gt;</span> std2<span class="op">::</span>println<span class="op">(</span>f64<span class="op">)</span>;</span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span>str<span class="op">(</span>str<span class="op">)</span> <span class="op">=&gt;</span> std2<span class="op">::</span>println<span class="op">(</span>str<span class="op">)</span>;</span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true" tabindex="-1"></a>  print<span class="op">(.</span>i32<span class="op">(</span><span class="dv">5</span><span class="op">))</span>;</span>
<span id="cb7-24"><a href="#cb7-24" aria-hidden="true" tabindex="-1"></a>  print<span class="op">(.</span>f32<span class="op">(</span><span class="fl">101.3</span><span class="bu">f</span><span class="op">))</span>;</span>
<span id="cb7-25"><a href="#cb7-25" aria-hidden="true" tabindex="-1"></a>  print<span class="op">(.</span>f64<span class="op">(</span><span class="fl">3.15159</span><span class="op">))</span>;</span>
<span id="cb7-26"><a href="#cb7-26" aria-hidden="true" tabindex="-1"></a>  print<span class="op">(.</span>str<span class="op">(</span><span class="st">&quot;Hello safety&quot;</span><span class="op">))</span>;</span>
<span id="cb7-27"><a href="#cb7-27" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Choice types are Safe C++’s type-safe offering. They’re just like
Rust’s enums, one of the features most credited for that language’s
modern ergonomics. Accessing members of a choice object requires testing
for the active type with a <em>match-expression</em>. If the match
succeeds, a new declaration is bound to the corresponding payload, and
that declaration is visible in the <em>match-body</em> following the
<code class="sourceCode cpp"><span class="op">=&gt;</span></code>.</p>
<p>The compiler also performs exhaustiveness testing on matches. Users
must name all the alternatives, or use a wildcard
<code class="sourceCode cpp">_</code> to default the unnamed ones.</p>
<p>Pattern matching and choice types aren’t just a qualify-of-life
improvement. They’re a critical part of the memory safety puzzle.</p>
<h3 data-number="1.5.3" id="thread-safety"><span class="header-section-number">1.5.3</span> Thread safety<a href="#thread-safety" class="self-link"></a></h3>
<p>A memory safe language should be robust against data races to shared
mutable state. If one thread is writing to shared state, no other thread
may access it. C++ is not thread safe language. Its synchronization
objects, such as
<code class="sourceCode cpp">std<span class="op">::</span>mutex</code>,
are opt-in. If a user reads shared mutable state from outside of a
mutex, that’s a potential data race. It’s up to users to coordinate that
the same synchronization objects are locked before accessing the same
shared mutable state.</p>
<p>Due to their non-deterministic nature, data race defects are
notoriously difficult to debug. Safe C++ prevents them from occurring in
the first place. Programs with potential data race bugs in the safe
context are ill-formed at compile time.</p>
<p>The thread safety model uses <a href="#send-and-sync">send and
sync</a> interfaces, <a href="#interior-mutability">interior
mutability</a> and <a href="#borrow-checking">borrow checking</a> to
establish a system of constraints guaranteeing that shared mutable state
is only accessed through synchronization primitives like
<code class="sourceCode cpp">std2<span class="op">::</span>mutex</code>.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/thread_safety.cxx"><strong>thread_safety.cxx</strong></a>
– <a href="https://godbolt.org/z/es9nx5sqd">(Compiler Explorer)</a></p>
<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="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;std2.h&gt;</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;chrono&gt;</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> <span class="kw">namespace</span> std2;</span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a><span class="co">// mutex is sync, so arc&lt;mutex&lt;string&gt;&gt; is send.</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> entry_point<span class="op">(</span>arc<span class="op">&lt;</span>mutex<span class="op">&lt;</span>string<span class="op">&gt;&gt;</span> data, <span class="dt">int</span> thread_id<span class="op">)</span> safe <span class="op">{</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Lock the data through the mutex.</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">// When lock_guard goes out of scope, the mutex is released.</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> lock_guard <span class="op">=</span> data<span class="op">-&gt;</span>lock<span class="op">()</span>;</span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Get a mutable borrow to the string data. When lock_guard goes out of</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>  <span class="co">// scope, this becomes a dangling pointer. The borrow checker prevents</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>  <span class="co">// us from accessing through dangling pointers.</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>  string<span class="op">^</span> s <span class="op">=</span> mut lock_guard<span class="op">.</span>borrow<span class="op">()</span>;</span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Append a fire and print the new shared state.</span></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true" tabindex="-1"></a>  s<span class="op">.</span>append<span class="op">(</span><span class="st">&quot;🔥&quot;</span><span class="op">)</span>;</span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Drop the lock before printing the shared state. This makes the borrow</span></span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true" tabindex="-1"></a>  <span class="co">// `s` a &quot;dangling pointer,&quot; in the sense that it depends on an expired</span></span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true" tabindex="-1"></a>  <span class="co">// lifetime. That will raise a borrowck error on `println(*s)`, which</span></span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true" tabindex="-1"></a>  <span class="co">// attempts to access shared state outside of the lock.</span></span>
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true" tabindex="-1"></a>  <span class="co">// drp lock_guard;</span></span>
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Drop the data before printing shared state. This decrements arc&#39;s</span></span>
<span id="cb8-28"><a href="#cb8-28" aria-hidden="true" tabindex="-1"></a>  <span class="co">// reference count and could potentially free the string data. It</span></span>
<span id="cb8-29"><a href="#cb8-29" aria-hidden="true" tabindex="-1"></a>  <span class="co">// raises a borrowck error on `println(*s)` because the borrow on `data`</span></span>
<span id="cb8-30"><a href="#cb8-30" aria-hidden="true" tabindex="-1"></a>  <span class="co">// from `data-&gt;lock()` is kept live by the use of `println(*s)` via the</span></span>
<span id="cb8-31"><a href="#cb8-31" aria-hidden="true" tabindex="-1"></a>  <span class="co">// borrow `mut lock_guard.borrow()`.</span></span>
<span id="cb8-32"><a href="#cb8-32" aria-hidden="true" tabindex="-1"></a>  <span class="co">// drp data;</span></span>
<span id="cb8-33"><a href="#cb8-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-34"><a href="#cb8-34" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Print the updated shared state.</span></span>
<span id="cb8-35"><a href="#cb8-35" aria-hidden="true" tabindex="-1"></a>  println<span class="op">(*</span>s<span class="op">)</span>;</span>
<span id="cb8-36"><a href="#cb8-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-37"><a href="#cb8-37" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Sleep 1s before returning.</span></span>
<span id="cb8-38"><a href="#cb8-38" aria-hidden="true" tabindex="-1"></a>  unsafe <span class="op">{</span> std<span class="op">::</span>this_thread<span class="op">::</span>sleep_for<span class="op">(</span>std<span class="op">::</span>chrono<span class="op">::</span>seconds<span class="op">(</span><span class="dv">1</span><span class="op">))</span>; <span class="op">}</span></span>
<span id="cb8-39"><a href="#cb8-39" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb8-40"><a href="#cb8-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-41"><a href="#cb8-41" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb8-42"><a href="#cb8-42" aria-hidden="true" tabindex="-1"></a>  <span class="co">// arc - Shared ownership.</span></span>
<span id="cb8-43"><a href="#cb8-43" aria-hidden="true" tabindex="-1"></a>  <span class="co">// mutex - Shared mutable access.</span></span>
<span id="cb8-44"><a href="#cb8-44" aria-hidden="true" tabindex="-1"></a>  arc<span class="op">&lt;</span>mutex<span class="op">&lt;</span>string<span class="op">&gt;&gt;</span> shared_data<span class="op">(</span>string<span class="op">(</span><span class="st">&quot;Hello world - &quot;</span><span class="op">))</span>;</span>
<span id="cb8-45"><a href="#cb8-45" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-46"><a href="#cb8-46" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Launch 10 threads.</span></span>
<span id="cb8-47"><a href="#cb8-47" aria-hidden="true" tabindex="-1"></a>  vector<span class="op">&lt;</span>thread<span class="op">&gt;</span> threads <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb8-48"><a href="#cb8-48" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span><span class="op">(</span><span class="dt">int</span> i <span class="op">:</span> <span class="dv">10</span><span class="op">)</span></span>
<span id="cb8-49"><a href="#cb8-49" aria-hidden="true" tabindex="-1"></a>    mut threads<span class="op">.</span>push_back<span class="op">(</span>thread<span class="op">(</span>entry_point, cpy shared_data, i<span class="op">))</span>;</span>
<span id="cb8-50"><a href="#cb8-50" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-51"><a href="#cb8-51" aria-hidden="true" tabindex="-1"></a>  <span class="co">// The consuming into_iterator produced by `rel threads` lets us relocate</span></span>
<span id="cb8-52"><a href="#cb8-52" aria-hidden="true" tabindex="-1"></a>  <span class="co">// elements out of the vector for the consuming thread::join call.</span></span>
<span id="cb8-53"><a href="#cb8-53" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span><span class="op">(</span>thread t <span class="op">:</span> rel threads<span class="op">)</span></span>
<span id="cb8-54"><a href="#cb8-54" aria-hidden="true" tabindex="-1"></a>    t rel<span class="op">.</span>join<span class="op">()</span>;</span>
<span id="cb8-55"><a href="#cb8-55" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb9"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>Hello world - 🔥</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>Hello world - 🔥🔥</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>Hello world - 🔥🔥🔥</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>Hello world - 🔥🔥🔥🔥</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>Hello world - 🔥🔥🔥🔥🔥</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>Hello world - 🔥🔥🔥🔥🔥🔥</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>Hello world - 🔥🔥🔥🔥🔥🔥🔥</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>Hello world - 🔥🔥🔥🔥🔥🔥🔥🔥</span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>Hello world - 🔥🔥🔥🔥🔥🔥🔥🔥🔥</span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>Hello world - 🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥</span></code></pre></div>
<p>We spawn ten threads which append a fire emoji to a shared string.
The string is stored in an
<code class="sourceCode cpp">std2<span class="op">::</span>mutex</code>
which is owned by an <code class="sourceCode cpp">arc</code>, which
stands for “atomic reference count.” The
<code class="sourceCode cpp">arc</code> provides <em>shared
ownership</em> of the data. The
<code class="sourceCode cpp">mutex</code> provides <em>shared
access</em> to it. C++ programmers often think that <code class="sourceCode cpp">std<span class="op">::</span>shared_ptr</code>
pointer provides safe shared access to objects. It does not. It only
provides shared ownership.</p>
<p><code class="sourceCode cpp">arc</code>’s accessor <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">-&gt;</span></code>
returns const-qualified borrows to the owned data. You can’t mutate
through most const-qualified types. You can only mutate through
const-qualified types that encapsulate
<code class="sourceCode cpp">unsafe_cell</code>, such as
<code class="sourceCode cpp">cell</code>,
<code class="sourceCode cpp">ref_cell</code>,
<code class="sourceCode cpp">mutex</code> and
<code class="sourceCode cpp">shared_mutex</code>. This is how <a href="#interior-mutability">interior mutability</a> implements shared
mutable access. The safe standard library provides
<code class="sourceCode cpp">mutex</code> and
<code class="sourceCode cpp">shared_mutex</code> which satisfy the <a href="#send-and-sync"><code class="sourceCode cpp">send</code> and
<code class="sourceCode cpp">sync</code></a> interfaces. Only types
satisfying <code class="sourceCode cpp">send</code> may be copied
through the
<code class="sourceCode cpp">std2<span class="op">::</span>thread</code>
constructor.</p>
<p>Inside the worker thread, we <code class="sourceCode cpp">lock</code>
the mutex to initialize a lock guard object. The lock guard is an RAII
type: on its construction the mutex is locked and on its destruction the
mutex is unlocked. We call <code class="sourceCode cpp">borrow</code> on
the lock guard to gain a mutable borrow to the string it contains. It’s
only correct to use the reference while the lock guard is in scope, that
is, while the thread has the mutex locked. Now we have exclusive access
to the string inside the mutex and append the fire emoji without risking
a data race.</p>
<p>But the thread safety isn’t yet demonstrated: the claim isn’t that we
<em>can</em> write thread safe software; the claim is that it’s
<em>ill-formed</em> to write thread unsafe software.</p>
<p>Let’s sabotage our own design. Uncomment the
<code class="sourceCode cpp">drp lock_guard</code> line. The lock guard
is destroyed and unlocks the mutex. The next statement prints the string
outside of the mutex, which is a data race, because one of the other
nine threads may at that instant be appending to the string.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>safety: during safety checking of void entry_point(std2::arc&lt;std2::mutex&lt;std2::string&gt;&gt;, int) safe</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>  borrow checking: thread_safety.cxx:35:12</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>    println(*s);</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>             ^</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>  use of s depends on expired loan</span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>  drop of lock_guard between its mutable borrow and its use</span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>  invalidating operation at thread_safety.cxx:25:3</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>    drp lock_guard;</span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>    ^</span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>  loan created at thread_safety.cxx:16:19</span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a>    string^ s = mut lock_guard.borrow();</span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a>                    ^</span></code></pre></div>
<p>Fortunately the borrow checker refuses to compile this function.
We’re informed that our use of <code class="sourceCode cpp">s</code> in
<code class="sourceCode cpp">println<span class="op">(*</span>s<span class="op">)</span></code>
depends on an expired loan, which is the loan on the lock guard that
gave us the string borrow in <code class="sourceCode cpp">mut lock_guard<span class="op">.</span>borrow<span class="op">()</span></code>.
That loan was invalidated when we dropped the lock guard: dropping a
place with a live borrow on it is a borrow checker error.</p>
<p>This time uncomment <code class="sourceCode cpp">drp data</code> to
destroy the thread’s copy of the <code class="sourceCode cpp">arc</code>
object. This decrements the ref count and potentially frees the string
data. This is undesirable, as the subsequent statement prints that same
string, and we don’t want a use-after-free bug.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>safety: during safety checking of void entry_point(std2::arc&lt;std2::mutex&lt;std2::string&gt;&gt;, int) safe</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>  borrow checking: thread_safety.cxx:32:3</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>    drp data;</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>    ^</span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>  drop of data between its shared borrow and its use</span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>  borrow kept live by drop of lock_guard declared at thread_safety.cxx:11:8</span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>    auto lock_guard = data-&gt;lock();</span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>         ^</span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>  loan created at thread_safety.cxx:11:21</span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>    auto lock_guard = data-&gt;lock();</span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>                      ^</span></code></pre></div>
<p>The borrow checker stops compilation. We’re dropping
<code class="sourceCode cpp">data</code>, which is the thread’s copy of
the <code class="sourceCode cpp">arc</code>, between its shared borrow
and its use. The expired borrow is created by <code class="sourceCode cpp">data<span class="op">-&gt;</span>lock<span class="op">()</span></code>,
which is our lock on the mutex: it creates a lifetime constraint on
<code class="sourceCode cpp">data</code>. That borrow is kept live after
the <code class="sourceCode cpp">drp data</code> by the lock guard’s
destructor, which unlocks the mutex in the
<code class="sourceCode cpp">arc</code>. The borrow checker won’t let us
drop <code class="sourceCode cpp">data</code>, because that conflicts
with an in-scope loan on that same object. The use-after-free defect is
avoided.</p>
<p>This is lifetime safety with an additional level of indirection
compared to the previous borrow checker violation. The beauty of borrow
checking is that, unlike lifetime safety based on heuristics, it’s
robust for any complicated set of constraints and control flow. The
thread safety it enables is superior concurrency technology than what
Standard C++ provides.</p>
<h3 data-number="1.5.4" id="runtime-checks"><span class="header-section-number">1.5.4</span> Runtime checks<a href="#runtime-checks" class="self-link"></a></h3>
<p>Safe operations that can’t be checked for soundness with static
analysis must be checked at runtime. An operation may return an error
code, throw an exception or panic and abort. Panics terminate the
program, which is far preferable from a security standpoint than
entering undefined behavior.</p>
<ul>
<li>Builtin arrays and slices panic on out-of-bounds subscripts.</li>
<li>Integer division panics when the divisor is zero or when the
numerator is INT_MIN and the divisor is -1.</li>
<li><code class="sourceCode cpp">std2<span class="op">::</span>vector</code>
panics on out-of-bounds subscripts.</li>
<li><code class="sourceCode cpp">std2<span class="op">::</span>ref_cell</code>
panics when requesting a mutable borrow and the inner object is borrowed
or when requesting a shared borrow and the inner object is mutably
borrowed.</li>
</ul>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/subscript_array.cxx"><strong>subscript_array.cxx</strong></a></p>
<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="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;cstdint&gt;</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> array<span class="op">[</span><span class="dv">4</span><span class="op">]</span> <span class="op">{</span> <span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span> <span class="op">}</span>;</span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">size_t</span> index <span class="op">=</span> <span class="dv">10</span>;</span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Panic on out-of-bounds array subscript.</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> x <span class="op">=</span> array<span class="op">[</span>index<span class="op">]</span>;</span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb13"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a>$ circle subscript_array.cxx</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>$ ./subscript_array</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>subscript_array.cxx:9:17</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>int main() safe</span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>subscript is out-of-range of type int[4]</span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>Aborted (core dumped)</span></code></pre></div>
<p>The compiler emits panics for out-of-bounds subscripts on builtin
arrays and slice types. The runtime can be elided with <a href="#unsafe-subscripts">unsafe subscripts</a>.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/subscript_vector.cxx"><strong>subscript_vector.cxx</strong></a></p>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;std2.h&gt;</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>  std2<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> vec <span class="op">{</span> <span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span> <span class="op">}</span>;</span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">size_t</span> index <span class="op">=</span> <span class="dv">10</span>;</span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Panic on out-of-bounds vector subscript.</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> x <span class="op">=</span> vec<span class="op">[</span>index<span class="op">]</span>;</span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb15"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>$ circle subscript_vector.cxx -I ../libsafecxx/single-header/</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>$ ./subscript_vector</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>../libsafecxx/single-header/std2.h:1684:39</span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>std2::vector&lt;int&gt;::operator[]</span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>vector subscript is out-of-bounds</span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>Aborted (core dumped)</span></code></pre></div>
<p>Out-of-contract use of user-defined types should panic with a similar
message. Unlike Standard C++, our containers always perform bounds
checking. As with builtin types, the runtime check can be elided with <a href="#unsafe-subscripts">unsafe subscripts</a> or disabled for the
entire translation unit with the <code class="sourceCode cpp"><span class="op">-</span>no<span class="op">-</span>panic</code>
compiler switch. This is a drastic measure and is intending for
profiling the effects of runtime checks.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">+&gt;</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> vector <span class="op">{</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> value_type<span class="op">^</span> <span class="kw">operator</span><span class="op">[](</span><span class="kw">const</span> self<span class="op">^</span>, size_type i<span class="op">)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>i <span class="op">&gt;=</span> self<span class="op">.</span>size<span class="op">())</span> panic_bounds<span class="op">(</span><span class="st">&quot;vector subscript is out-of-bounds&quot;</span><span class="op">)</span>;</span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>    unsafe <span class="op">{</span> <span class="cf">return</span> <span class="op">^</span>self<span class="op">.</span>data<span class="op">()[</span>i<span class="op">]</span>; <span class="op">}</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>The <a href="#memory-safety-as-terms-and-conditions">safety model</a>
establishes rules for where library code must insert panic calls. If a
function is marked safe but is internally unsound for some values of its
arguments, it should check those arguments and panic before executing
the unsafe operation. Unsafe functions generally don’t panic because its
the responsibility of their callers to observe the preconditions of the
function.</p>
<h1 data-number="2" id="design-overview"><span class="header-section-number">2</span> Design overview<a href="#design-overview" class="self-link"></a></h1>
<h2 data-number="2.1" id="the-safe-context"><span class="header-section-number">2.1</span> The
<code class="sourceCode cpp">safe</code> context<a href="#the-safe-context" class="self-link"></a></h2>
<p>Operations in the safe context are guaranteed not to cause undefined
behavior. Some operations linked to undefined behavior can’t be vetted
by the frontend, during MIR analysis or with panics at runtime.
Attempting to use them in the safe context makes the program ill-formed.
These operations are:</p>
<ul>
<li>Dereference of pointers and legacy references. This may result in
use-after-free undefined behaviors. Prefer using borrows, which exhibit
lifetime safety thanks to the borrow checker.</li>
<li>Pointer offsets. Advancing a pointer past the end of its allocation
is undefined behavior. Prefer using slices, which include bounds
information.</li>
<li>Pointer difference. Taking the difference of pointers into different
allocations is undefined behavior.</li>
<li>Pointer relational operators &lt;, &lt;=, &gt; and &gt;=. Comparing
pointers into different allocations is undefined behavior.</li>
<li>Accessing fields of unions. Legacy unions present a type safety
hazard. Prefer using choice types.</li>
<li>Naming mutable objects with static storage duration. This is a data
race hazard, as different users may be writing to and reading from the
same memory simultaneously. This is even a hazard with
<code class="sourceCode cpp"><span class="kw">thread_local</span></code>
storage, as the law of exclusivity cannot be upheld for shared mutable
access within a single thread.</li>
<li>Inline ASM. The compiler generally isn’t equipped to determine if
inline ASM is safe, so its usage in the safe context is banned.</li>
<li>Calling unsafe functions. This is banned because the unsafe function
may involve any of the above operations.</li>
</ul>
<p>The compiler lowers function definitions to mid-level IR (MIR) and
performs initialization analysis and borrow checking. These issues are
found by data flow analysis, making your program ill-formed, regardless
of the safe context:</p>
<ul>
<li>Use of uninitialized, partially initialized or potentially
initialized objects is ill-formed. This is checked by initialization
analysis.</li>
<li>A conflicting action on an overlapping place with an in-scope loan
is a borrow checker error. This includes use-after-free and iterator
invalidation issues. The law of exclusivity is enforced as part of this
check.</li>
<li>Free region errors. The borrow checker upholds that lifetimes on
function parameters do not outlive the constraints defined on the
function’s declaration. This ensures that the caller and callee agree on
the lifetimes of arguments and result objects. It enables what is
essentially inter-procedural live analysis without attempting very
expensive whole-program analysis.</li>
</ul>
<p>Some operations are potentially unsound, but can be checked at
runtime. If the check fails, the program panics and aborts. <a href="#runtime-checks">Runtime checks</a> are enforced regardless of the
safe context.</p>
<h3 data-number="2.1.1" id="safe-specifier"><span class="header-section-number">2.1.1</span> <em>safe-specifier</em><a href="#safe-specifier" class="self-link"></a></h3>
<p>As with the <em>noexcept-specifier</em>, function types and
declarations may be marked with a <em>safe-specifier</em>. Position this
after the <em>noexcept-specifier</em>. Types and functions without the
<em>noexcept-specifer</em> are assumed to be potentially throwing.
Similarly, types and functions without the <em>safe-specifier</em> are
assumed to be unsafe.</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="co">// `safe` is part of the function type.</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> F1 <span class="op">=</span> <span class="dt">void</span><span class="op">(</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> F2 <span class="op">=</span> <span class="dt">void</span><span class="op">(</span><span class="dt">int</span><span class="op">)</span> safe;</span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> F3 <span class="op">=</span> <span class="dt">void</span><span class="op">(</span><span class="dt">int</span><span class="op">)</span> <span class="kw">noexcept</span>;</span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> F4 <span class="op">=</span> <span class="dt">void</span><span class="op">(</span><span class="dt">int</span><span class="op">)</span> <span class="kw">noexcept</span> safe;</span></code></pre></div>
<p>As with
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>,
<code class="sourceCode cpp">safe</code> is part of the function’s type,
so types with different <em>safe-specifiers</em> always compare
differently:</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="co">// `safe` is part of the function type.</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>F1 <span class="op">!=</span> F2<span class="op">)</span>;</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>F3 <span class="op">!=</span> F4<span class="op">)</span>;</span></code></pre></div>
<p>Just like
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>,
the safeness of a function’s type can be stripped during standard
conversion of function pointers. It’s unsound to add a
<em>safe-specifier</em> during conversions, as it is with
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>, so
that’s prohibited.</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="co">// You can strip off `safe` in function pointers.</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>std<span class="op">::</span>is_convertible_v<span class="op">&lt;</span>F2<span class="op">*</span>, F1<span class="op">*&gt;)</span>;</span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>std<span class="op">::</span>is_convertible_v<span class="op">&lt;</span>F4<span class="op">*</span>, F3<span class="op">*&gt;)</span>;</span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a><span class="co">// You can strip off both `noexcept` and `safe`.</span></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>std<span class="op">::</span>is_convertible_v<span class="op">&lt;</span>F4<span class="op">*</span>, F1<span class="op">*&gt;)</span>;</span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a><span class="co">// You can&#39;t add safe. That&#39;s unsafe.</span></span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(!</span>std<span class="op">::</span>is_convertible_v<span class="op">&lt;</span>F1<span class="op">*</span>, F2<span class="op">*&gt;)</span>;</span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(!</span>std<span class="op">::</span>is_convertible_v<span class="op">&lt;</span>F3<span class="op">*</span>, F4<span class="op">*&gt;)</span>;</span></code></pre></div>
<p>Declaring functions with value-dependent <em>safe-specifiers</em> is
supported. Query the safeness of an expression in an unevaluated context
with the <em>safe-operator</em>. It’s analagous to the existing
<em>noexcept-operator</em>. It’s useful when paired with
<em>requires-clause</em>, as it lets you constrain inputs based on the
safeness of a callable.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/safe.cxx"><strong>safe.cxx</strong></a></p>
<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="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> F, <span class="kw">typename</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> spawn<span class="op">(</span>F f, Args<span class="op">...</span> args<span class="op">)</span> safe <span class="kw">requires</span><span class="op">(</span>safe<span class="op">(</span>f<span class="op">(</span>args<span class="op">...)))</span>;</span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Foo <span class="op">{</span></span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// The int overload is safe.</span></span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> <span class="kw">operator</span><span class="op">()(</span><span class="kw">const</span> self<span class="op">^</span>, <span class="dt">int</span><span class="op">)</span> safe;</span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">// The double overload is unsafe.</span></span>
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> <span class="kw">operator</span><span class="op">()(</span><span class="kw">const</span> self<span class="op">^</span>, <span class="dt">double</span><span class="op">)</span>;</span>
<span id="cb20-12"><a href="#cb20-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb20-13"><a href="#cb20-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-14"><a href="#cb20-14" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb20-15"><a href="#cb20-15" aria-hidden="true" tabindex="-1"></a>  Foo obj <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb20-16"><a href="#cb20-16" aria-hidden="true" tabindex="-1"></a>  spawn<span class="op">(</span>obj, <span class="dv">1</span><span class="op">)</span>;   <span class="co">// OK</span></span>
<span id="cb20-17"><a href="#cb20-17" aria-hidden="true" tabindex="-1"></a>  spawn<span class="op">(</span>obj, <span class="fl">1.1</span><span class="op">)</span>; <span class="co">// Ill-formed. Fails requires-clause.</span></span>
<span id="cb20-18"><a href="#cb20-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb21"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>$ circle safe.cxx</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>error: safe.cxx:17:8</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>  spawn(obj, 1.1); // Ill-formed. Fails requires-clause.</span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>       ^</span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>error during overload resolution for spawn</span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>  instantiation: safe.cxx:4:6</span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>  void spawn(F f, Args... args) safe requires(safe(f(args...)));</span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a>       ^</span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a>  template arguments: [</span>
<span id="cb21-11"><a href="#cb21-11" aria-hidden="true" tabindex="-1"></a>    F = Foo</span>
<span id="cb21-12"><a href="#cb21-12" aria-hidden="true" tabindex="-1"></a>      class Foo declared at safe.cxx:6:1</span>
<span id="cb21-13"><a href="#cb21-13" aria-hidden="true" tabindex="-1"></a>    Args#0 = double</span>
<span id="cb21-14"><a href="#cb21-14" aria-hidden="true" tabindex="-1"></a>  ]</span>
<span id="cb21-15"><a href="#cb21-15" aria-hidden="true" tabindex="-1"></a>    constraint: safe.cxx:4:45</span>
<span id="cb21-16"><a href="#cb21-16" aria-hidden="true" tabindex="-1"></a>    void spawn(F f, Args... args) safe requires(safe(f(args...)));</span>
<span id="cb21-17"><a href="#cb21-17" aria-hidden="true" tabindex="-1"></a>                                                ^</span>
<span id="cb21-18"><a href="#cb21-18" aria-hidden="true" tabindex="-1"></a>    spawn fails requires-clause (safe(f(args...)))</span></code></pre></div>
<p>Consider a <code class="sourceCode cpp">spawn</code> function that
takes a callable <code class="sourceCode cpp">f</code> and a set of
arguments <code class="sourceCode cpp">args</code>. The function is
marked <code class="sourceCode cpp">safe</code>. Transitively, the
callable, when invoked with the provided arguments, must also be a safe
operation. But we can’t stipulate
<code class="sourceCode cpp">safe</code> on the type
<code class="sourceCode cpp">F</code>, because it may not be a function
type. Here it’s a class with two overloaded call operators.</p>
<p>When the user provides an integer argument, the
<em>requires-clause</em> substitutes to <code class="sourceCode cpp">safe<span class="op">(</span>f<span class="op">(</span><span class="dv">1</span><span class="op">))</span></code>,
which is true, because the best viable candidate for the function call
is <code class="sourceCode cpp"><span class="dt">void</span> <span class="kw">operator</span><span class="op">()(</span><span class="kw">const</span> self<span class="op">^</span>, <span class="dt">int</span><span class="op">)</span> safe;</code>.
That’s a safe function.</p>
<p>When the user provides a floating-point argument, the
<em>requires-clause</em> substitutes to <code class="sourceCode cpp">safe<span class="op">(</span>f<span class="op">(</span><span class="fl">1.1</span><span class="op">))</span></code>,
which is false, because the best viable candidate is <code class="sourceCode cpp"><span class="dt">void</span> <span class="kw">operator</span><span class="op">()(</span><span class="kw">const</span> self<span class="op">^</span>, <span class="dt">double</span><span class="op">)</span>;</code>.
That’s not a safe function.</p>
<h3 data-number="2.1.2" id="unsafe-block"><span class="header-section-number">2.1.2</span> <em>unsafe-block</em><a href="#unsafe-block" class="self-link"></a></h3>
<p>The <code class="sourceCode cpp">unsafe</code> token escapes the safe
context, permitting operations for which soundness cannot be guaranteed
by the compiler. The primary unsafe escape is the <em>unsafe-block</em>.
At the statement level, write <code class="sourceCode cpp">unsafe <span class="op">{</span> <span class="op">}</span></code>
with the unsafe operations inside the braces. Unlike in Rust,
<em>unsafe-blocks</em> do <em>not</em> open new lexical scopes.</p>
<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="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> func<span class="op">(</span><span class="kw">const</span> <span class="dt">int</span><span class="op">*</span> p<span class="op">)</span> safe <span class="op">{</span></span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Most pointer operations are unsafe. Use unsafe-block to perform them in</span></span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// a safe function.</span></span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Pointer offset is unsafe.</span></span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a>  unsafe <span class="op">{</span> <span class="op">++</span>p; <span class="op">}</span></span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Put multiple statements in an unsafe-block.</span></span>
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a>  unsafe <span class="op">{</span></span>
<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Pointer difference is unsafe.</span></span>
<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a>    <span class="dt">ptrdiff_t</span> diff <span class="op">=</span> p <span class="op">-</span> p;</span>
<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-15"><a href="#cb22-15" aria-hidden="true" tabindex="-1"></a>    <span class="co">// unsafe-blocks do not open lexical scopes. Declarations will be</span></span>
<span id="cb22-16"><a href="#cb22-16" aria-hidden="true" tabindex="-1"></a>    <span class="co">// visible below.</span></span>
<span id="cb22-17"><a href="#cb22-17" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> x <span class="op">=</span> p<span class="op">[</span><span class="dv">4</span><span class="op">]</span>;</span>
<span id="cb22-18"><a href="#cb22-18" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb22-19"><a href="#cb22-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-20"><a href="#cb22-20" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Can use unsafe-block like compound-statement inside control flow.</span></span>
<span id="cb22-21"><a href="#cb22-21" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span><span class="op">(</span>x <span class="op">==</span> <span class="dv">1</span><span class="op">)</span> unsafe <span class="op">{</span> <span class="cf">return</span> p<span class="op">[</span><span class="dv">5</span><span class="op">]</span>; <span class="op">}</span></span>
<span id="cb22-22"><a href="#cb22-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-23"><a href="#cb22-23" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> x;</span>
<span id="cb22-24"><a href="#cb22-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Unsafe blocks are appear in different forms in a few places:</p>
<ul>
<li>Before subobject <em>mem-initializer</em>.</li>
<li>Before <em>condition</em> expressions.</li>
<li>Before <em>match-body</em> in a <em>match-clause</em>.</li>
</ul>
<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="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a><span class="co">// Unsafe function.</span></span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> func<span class="op">()</span>;</span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Foo <span class="op">{</span></span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// This constructor is safe, but the mem-initializer is unsafe.</span></span>
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Use an unsafe-block here.</span></span>
<span id="cb23-9"><a href="#cb23-9" aria-hidden="true" tabindex="-1"></a>  Foo<span class="op">()</span> safe <span class="op">:</span> unsafe b<span class="op">(</span>func<span class="op">())</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb23-10"><a href="#cb23-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> b;</span>
<span id="cb23-11"><a href="#cb23-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb23-12"><a href="#cb23-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-13"><a href="#cb23-13" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb23-14"><a href="#cb23-14" aria-hidden="true" tabindex="-1"></a>  <span class="co">// main() is safe, but the if-condition is unsafe.</span></span>
<span id="cb23-15"><a href="#cb23-15" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Use an unsafe-block.</span></span>
<span id="cb23-16"><a href="#cb23-16" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span><span class="op">(</span>unsafe func<span class="op">())</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb23-17"><a href="#cb23-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-18"><a href="#cb23-18" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> x <span class="op">=</span> match<span class="op">(</span><span class="dv">1</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb23-19"><a href="#cb23-19" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Use an unsafe block in the match-body.</span></span>
<span id="cb23-20"><a href="#cb23-20" aria-hidden="true" tabindex="-1"></a>    _ <span class="op">=&gt;</span> unsafe func<span class="op">()</span>;</span>
<span id="cb23-21"><a href="#cb23-21" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb23-22"><a href="#cb23-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>In all cases, <code class="sourceCode cpp">unsafe</code> is an
auditable token where the user expressly takes responsibility for sound
execution.</p>
<h3 data-number="2.1.3" id="the-unsafe-type-qualifier"><span class="header-section-number">2.1.3</span> The
<code class="sourceCode cpp">unsafe</code> type qualifier<a href="#the-unsafe-type-qualifier" class="self-link"></a></h3>
<p>The Rust ecosystem was built from the bottom-up prioritizing safe
code. Consequently, there’s so little unsafe code that the
<em>unsafe-block</em> is generally sufficient for interfacing with it.
By contrast, there are many billions of lines of unsafe C++. The
<em>unsafe-block</em> isn’t powerful enough to interface our safe and
unsafe assets, as we’d be writing <em>unsafe-blocks</em> everywhere,
making a noisy mess. Worse, we’d be unable to use unsafe types from safe
function templates, since the template definition wouldn’t know it was
dealing with unsafe template parameters. Because of the ecosystem
difference, Rust does not provide guidance for this problem, and we’re
left to our own devices.</p>
<p><strong>Safe C++’s answer to safe/unsafe interoperability is to make
safeness part of the type system.</strong></p>
<p>Standard C++ has
<code class="sourceCode cpp"><span class="kw">const</span></code> and
<code class="sourceCode cpp"><span class="kw">volatile</span></code>
type qualifiers. Safe C++ adds the
<code class="sourceCode cpp">unsafe</code> type qualifier. Declare an
object or data member with the
<code class="sourceCode cpp">unsafe</code> qualifier and use it freely
<em>even in safe contexts</em>. The
<code class="sourceCode cpp">unsafe</code> token means the same thing
here as it does with <em>unsafe-blocks</em>: the programmer is assuming
responsibility for upholding the requirements of the unsafe-qualifed
type. If something is unsound, blame lies with the
<code class="sourceCode cpp">unsafe</code> wielder.</p>
<p>Naming an unsafe object yields an lvalue expression of the unsafe
type. What are the effects of the unsafe qualifier on an expression? In
a safe context:</p>
<ul>
<li>Calling unsafe member functions on unsafe-qualified objects is
permitted.</li>
<li>Calling unsafe functions where a function argument is
unsafe-qualified is permitted.</li>
<li>Unsafe constructors may initialize unsafe types.</li>
</ul>
<p>Expressions carry
<code class="sourceCode cpp"><span class="kw">noexcept</span></code> and
<code class="sourceCode cpp">safe</code> states, which is how
<em>noexcept-operator</em> and <em>safe-specifier</em> are implemented.
Those states are separate from the type of the expression. Why make
<code class="sourceCode cpp">unsafe</code> a type qualifier, which
represents a significant change to the type system, rather than a
property of an expresion like those
<code class="sourceCode cpp"><span class="kw">noexcept</span></code> and
<code class="sourceCode cpp">safe</code> states?</p>
<p>The answer is that template specialization works on types and it
doesn’t work on these other states of an expression. A template argument
with an unsafe type qualifier instantiates a template with an unsafe
type qualifier on the corresponding template parameter. The unsafe
qualifier drills through templates in a way that other language entities
don’t.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/unsafe2.cxx"><strong>unsafe2.cxx</strong></a>
– <a href="https://godbolt.org/z/7qEnb4s44">(Compiler Explorer)</a></p>
<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="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;std2.h&gt;</span></span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;string&gt;</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Requires unsafe type specifier because std::string&#39;s dtor is unsafe.</span></span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a>  std2<span class="op">::</span>vector<span class="op">&lt;</span>unsafe std<span class="op">::</span>string<span class="op">&gt;</span> vec <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Construct an std::string from a const char* (unsafe)</span></span>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Pass by relocation (unsafe)</span></span>
<span id="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a>  mut vec<span class="op">.</span>push_back<span class="op">(</span><span class="st">&quot;Hello unsafe type qualifier!&quot;</span><span class="op">)</span>;</span>
<span id="cb24-12"><a href="#cb24-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-13"><a href="#cb24-13" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Append Bar to the end of Foo (unsafe)</span></span>
<span id="cb24-14"><a href="#cb24-14" aria-hidden="true" tabindex="-1"></a>  mut vec<span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">+=</span> <span class="st">&quot;Another unsafe string&quot;</span>;</span>
<span id="cb24-15"><a href="#cb24-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-16"><a href="#cb24-16" aria-hidden="true" tabindex="-1"></a>  std2<span class="op">::</span>println<span class="op">(</span>vec<span class="op">[</span><span class="dv">0</span><span class="op">])</span>;</span>
<span id="cb24-17"><a href="#cb24-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>We want to use the new memory safe vector with the legacy string
type. The new vector is borrow checked, eliminating use-after-free and
iterator invalidation defects. It presents a safe interface. But the old
string is pre-safety. All its member functions are unsafe. We want to
specialize the new vector on the old string, so we mark it
<code class="sourceCode cpp">unsafe</code>.</p>
<p>The unsafe type qualifier propagates through the instantiated vector.
The expressions returned from the <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">[]</span></code>
accessor are unsafe qualified, allowing us to call unsafe member
functions on the string, even in main’s safe context.</p>
<p>Let’s simplify the example above and study it in detail.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/unsafe3.cxx"><strong>unsafe3.cxx</strong></a></p>
<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="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">+&gt;</span></span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Vec <span class="op">{</span></span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a>  Vec<span class="op">()</span> safe;</span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> push_back<span class="op">(</span>self<span class="op">^</span>, T obj<span class="op">)</span> safe;</span>
<span id="cb25-7"><a href="#cb25-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb25-8"><a href="#cb25-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-9"><a href="#cb25-9" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> String <span class="op">{</span></span>
<span id="cb25-10"><a href="#cb25-10" aria-hidden="true" tabindex="-1"></a>  String<span class="op">(</span><span class="kw">const</span> <span class="dt">char</span><span class="op">*)</span>; <span class="co">// Unsafe ctor.</span></span>
<span id="cb25-11"><a href="#cb25-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb25-12"><a href="#cb25-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-13"><a href="#cb25-13" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb25-14"><a href="#cb25-14" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Vec has a safe constructor.</span></span>
<span id="cb25-15"><a href="#cb25-15" aria-hidden="true" tabindex="-1"></a>  Vec<span class="op">&lt;</span>unsafe String<span class="op">&gt;</span> vec <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb25-16"><a href="#cb25-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-17"><a href="#cb25-17" aria-hidden="true" tabindex="-1"></a>  <span class="co">// void Vec&lt;unsafe String&gt;::push_back(self^, unsafe String) safe;</span></span>
<span id="cb25-18"><a href="#cb25-18" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Copy initialization of the `unsafe String` function parameter is</span></span>
<span id="cb25-19"><a href="#cb25-19" aria-hidden="true" tabindex="-1"></a>  <span class="co">// permitted.</span></span>
<span id="cb25-20"><a href="#cb25-20" aria-hidden="true" tabindex="-1"></a>  mut vec<span class="op">.</span>push_back<span class="op">(</span><span class="st">&quot;A string&quot;</span><span class="op">)</span>;</span>
<span id="cb25-21"><a href="#cb25-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>In this example, the unsafe
<code class="sourceCode cpp">String</code> constructor is called in the
safe <code class="sourceCode cpp">main</code> function. That’s permitted
because substitution of
<code class="sourceCode cpp">unsafe String</code> into Vec’s template
parameter creates a <code class="sourceCode cpp">push_back</code>
specialization with an <code class="sourceCode cpp">unsafe String</code>
function parameter. Safe C++ allows unsafe constructors to initialize
unsafe-qualified types in an safe context.</p>
<p>Permitting unsafe operations with unsafe qualifier specialization is
less noisy and exposes less of the implementation than using conditional
<em>unsafe-specifiers</em> on the class template’s member functions.
More importantly, we want to keep the new vector’s interface safe, even
when it’s specialized with unsafe types. This device allows member
functions to remain safe without resorting to <em>unsafe-blocks</em> in
the implementations. There’s a single use of the
<code class="sourceCode cpp">unsafe</code> token, which makes for simple
audits during code review.</p>
<p>Placing the unsafe token on the <em>template-argument-list</em>,
where the class template gets used, is far preferable to enclosing
operations on the template parameter type in <em>unsafe-blocks</em>
inside the template. In the former case, the user of the container can
read its preconditions and swear that the precondidions are met. In the
latter case, the template isn’t able to make any statements about
properly using the template type, because it doesn’t know what that type
is. The <code class="sourceCode cpp">unsafe</code> token should go with
the caller, not the callee.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/unsafe4.cxx"><strong>unsafe4.cxx</strong></a></p>
<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><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">+&gt;</span></span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Vec <span class="op">{</span></span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a>  Vec<span class="op">()</span> safe;</span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> push_back<span class="op">(</span>self<span class="op">^</span>, T obj<span class="op">)</span> safe;</span>
<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb26-8"><a href="#cb26-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-9"><a href="#cb26-9" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> String <span class="op">{</span></span>
<span id="cb26-10"><a href="#cb26-10" aria-hidden="true" tabindex="-1"></a>  String<span class="op">(</span><span class="kw">const</span> <span class="dt">char</span><span class="op">*)</span>; <span class="co">// Unsafe ctor.</span></span>
<span id="cb26-11"><a href="#cb26-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb26-12"><a href="#cb26-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-13"><a href="#cb26-13" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb26-14"><a href="#cb26-14" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Vec has a safe constructor.</span></span>
<span id="cb26-15"><a href="#cb26-15" aria-hidden="true" tabindex="-1"></a>  Vec<span class="op">&lt;</span>unsafe String<span class="op">&gt;</span> vec <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb26-16"><a href="#cb26-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-17"><a href="#cb26-17" aria-hidden="true" tabindex="-1"></a>  <span class="co">// void Vec&lt;unsafe String&gt;::push_back(self^, unsafe String) safe;</span></span>
<span id="cb26-18"><a href="#cb26-18" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Copy initialization of the `unsafe String` function parameter is</span></span>
<span id="cb26-19"><a href="#cb26-19" aria-hidden="true" tabindex="-1"></a>  <span class="co">// permitted.</span></span>
<span id="cb26-20"><a href="#cb26-20" aria-hidden="true" tabindex="-1"></a>  mut vec<span class="op">.</span>push_back<span class="op">(</span><span class="st">&quot;A string&quot;</span><span class="op">)</span>;</span>
<span id="cb26-21"><a href="#cb26-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb27"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a>$ circle unsafe4.cxx</span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>error: unsafe4.cxx:20:27</span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a>  mut vec.push_back(String(&quot;A string&quot;));</span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a>                          ^</span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a>cannot call unsafe constructor String::String(const char*) in safe context</span>
<span id="cb27-6"><a href="#cb27-6" aria-hidden="true" tabindex="-1"></a>see declaration at unsafe4.cxx:10:3</span></code></pre></div>
<p>This code is ill-formed. It’s permissible to invoke an unsafe
constructor when copy-initializing into the
<code class="sourceCode cpp">push_back</code> call, since its function
parameter is <code class="sourceCode cpp">unsafe String</code>. Dut
direct initialization of <code class="sourceCode cpp">String</code> is
not allowed. The constructor chosen for direct initialization is unsafe,
but the type it’s initializing is not. The type is just
<code class="sourceCode cpp">String</code>. The compiler is right to
reject this program because the user is plainly calling an unsafe
constructor in a safe context, without a mitigating
<em>unsafe-block</em> or unsafe qualifier.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/unsafe5.cxx"><strong>unsafe5.cxx</strong></a></p>
<div class="sourceCode" id="cb28"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">+&gt;</span></span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Vec <span class="op">{</span></span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a>  Vec<span class="op">()</span> safe;</span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> push_back<span class="op">(</span>self<span class="op">^</span>, T obj<span class="op">)</span> safe;</span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> emplace_back<span class="op">(</span>self<span class="op">^</span>, Ts<span class="op">...</span> obj<span class="op">)</span> safe <span class="op">{</span></span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Direct initialization with the String(const char*) ctor.</span></span>
<span id="cb28-11"><a href="#cb28-11" aria-hidden="true" tabindex="-1"></a>    <span class="co">// This compiles, because T is unsafe-qualified.</span></span>
<span id="cb28-12"><a href="#cb28-12" aria-hidden="true" tabindex="-1"></a>    self<span class="op">.</span>push_back<span class="op">(</span>T<span class="op">(</span>rel obj<span class="op">...))</span>;</span>
<span id="cb28-13"><a href="#cb28-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb28-14"><a href="#cb28-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb28-15"><a href="#cb28-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-16"><a href="#cb28-16" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> String <span class="op">{</span></span>
<span id="cb28-17"><a href="#cb28-17" aria-hidden="true" tabindex="-1"></a>  String<span class="op">(</span><span class="kw">const</span> <span class="dt">char</span><span class="op">*)</span>; <span class="co">// Unsafe ctor.</span></span>
<span id="cb28-18"><a href="#cb28-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb28-19"><a href="#cb28-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-20"><a href="#cb28-20" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb28-21"><a href="#cb28-21" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Vec has a safe constructor.</span></span>
<span id="cb28-22"><a href="#cb28-22" aria-hidden="true" tabindex="-1"></a>  Vec<span class="op">&lt;</span>unsafe String<span class="op">&gt;</span> vec <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb28-23"><a href="#cb28-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-24"><a href="#cb28-24" aria-hidden="true" tabindex="-1"></a>  <span class="co">// void Vec&lt;unsafe String&gt;::emplace_back(self^, const char*) safe;</span></span>
<span id="cb28-25"><a href="#cb28-25" aria-hidden="true" tabindex="-1"></a>  mut vec<span class="op">.</span>emplace_back<span class="op">(</span><span class="st">&quot;A string&quot;</span><span class="op">)</span>;</span>
<span id="cb28-26"><a href="#cb28-26" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This program is well-formed. As with the previous example, there’s a
direct initialization of a String object using its unsafe constructor.
This time it’s allowed, because the type being initialized is
<code class="sourceCode cpp">T</code>, which is substituted with
<code class="sourceCode cpp">unsafe String</code>: unsafe constructors
are permitted to initialize unsafe types.</p>
<p>The <a href="#the-unsafe-type-qualifier">unsafe type qualifier</a> is
a powerful mechanism for incorporating legacy code into new, safe
templates. But propagating the qualifier through all template parameters
may be too permissive. C++ templates won’t be expecting the
<code class="sourceCode cpp">unsafe</code> qualifier, and it may break
dependencies. Functions that are explicitly instantiated won’t have
<code class="sourceCode cpp">unsafe</code> instantiations, and that
would cause link errors. It may be prudent to get some usage experience,
and limit this type qualifier to being deduced only by type template
parameters with a certain token, eg <code class="sourceCode cpp"><span class="kw">typename</span> T<span class="op">?</span></code>.
That way, <code class="sourceCode cpp"><span class="kw">typename</span> T<span class="op">+?</span></code>
would become a common incantation for containers: create template
lifetime parameters for this template parameter <em>and</em> deduce the
<code class="sourceCode cpp">unsafe</code> qualifier for it.</p>
<p>To be more accommodating when mixing unsafe with safe code, the
<code class="sourceCode cpp">unsafe</code> qualifier has very liberal
transitive properties. A function invoked with an unsafe-qualified
object or argument, or a constructor that initializes an unsafe type,
are <em>exempted calls</em>. When performing overload resolution for
exempted calls, function parameters of candidates become unsafe
qualified. This permits copy initialization of function arguments into
parameter types when any argument is unsafe qualified. The intent is to
make deployment of the <code class="sourceCode cpp">unsafe</code> token
more strategic: use it less often but make it more impactful. It’s not
helpful to dilute its potency with many trivial <em>unsafe-block</em>
operations.</p>
<h3 data-number="2.1.4" id="unsafe-subscripts"><span class="header-section-number">2.1.4</span> unsafe subscripts<a href="#unsafe-subscripts" class="self-link"></a></h3>
<p>There’s one more prominent use of the
<code class="sourceCode cpp">unsafe</code> token: it suppresses runtime
bounds checks in subscript operations on both builtin and user-defined
types. For applications where nanoseconds matter, developers may want to
forego runtime bounds checking. In Safe C++, this is straight forward.
Just write <code class="sourceCode cpp">; unsafe</code> in your array,
slice or vector subscript.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/unsafe_bounds.cxx"><strong>unsafe_bounds.cxx</strong></a>
– <a href="https://godbolt.org/z/9xajqhrvc">(Compiler Explorer)</a></p>
<div class="sourceCode" id="cb29"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;std2.h&gt;</span></span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> subscript_array<span class="op">([</span><span class="dt">int</span>; <span class="dv">10</span><span class="op">]</span> array, <span class="dt">size_t</span> i, <span class="dt">size_t</span> j<span class="op">)</span> safe <span class="op">{</span></span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a>  array<span class="op">[</span>i; unsafe<span class="op">]</span> <span class="op">+=</span> array<span class="op">[</span>j; unsafe<span class="op">]</span>;</span>
<span id="cb29-6"><a href="#cb29-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb29-7"><a href="#cb29-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-8"><a href="#cb29-8" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> subscript_slice<span class="op">([</span><span class="dt">int</span>; dyn<span class="op">]^</span> slice, <span class="dt">size_t</span> i, <span class="dt">size_t</span> j<span class="op">)</span> safe <span class="op">{</span></span>
<span id="cb29-9"><a href="#cb29-9" aria-hidden="true" tabindex="-1"></a>  slice<span class="op">[</span>i; unsafe<span class="op">]</span> <span class="op">+=</span> slice<span class="op">[</span>j; unsafe<span class="op">]</span>;</span>
<span id="cb29-10"><a href="#cb29-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb29-11"><a href="#cb29-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-12"><a href="#cb29-12" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> subscript_vector<span class="op">(</span>std2<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> vec, <span class="dt">size_t</span> i, <span class="dt">size_t</span> j<span class="op">)</span> safe <span class="op">{</span></span>
<span id="cb29-13"><a href="#cb29-13" aria-hidden="true" tabindex="-1"></a>  mut vec<span class="op">[</span>i; unsafe<span class="op">]</span> <span class="op">+=</span> vec<span class="op">[</span>j; unsafe<span class="op">]</span>;</span>
<span id="cb29-14"><a href="#cb29-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The unsafe subscript indicates that runtime bounds checks is relaxed,
while keeping a consistent syntax with ordinary checked subscripts. It
doesn’t expose any operations to an unsafe context. The use of the
<code class="sourceCode cpp">unsafe</code> token is the programmer’s way
of taking responsibility for correct behavior.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/unsafe_bounds.rs"><strong>unsafe_bounds.rs</strong></a></p>
<div class="sourceCode" id="cb2"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> subscript_array(<span class="kw">mut</span> array<span class="op">:</span> [<span class="dt">i32</span><span class="op">;</span> <span class="dv">10</span>]<span class="op">,</span> i<span class="op">:</span> <span class="dt">usize</span><span class="op">,</span> j<span class="op">:</span> <span class="dt">usize</span>) <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">unsafe</span> <span class="op">{</span> <span class="op">*</span>array<span class="op">.</span>get_unchecked_mut(i) <span class="op">+=</span> <span class="op">*</span>array<span class="op">.</span>get_unchecked(j)<span class="op">;</span> <span class="op">}</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> subcript_slice(slice<span class="op">:</span> <span class="op">&amp;</span><span class="kw">mut</span> [<span class="dt">i32</span>]<span class="op">,</span> i<span class="op">:</span> <span class="dt">usize</span><span class="op">,</span> j<span class="op">:</span> <span class="dt">usize</span>) <span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">unsafe</span> <span class="op">{</span> <span class="op">*</span>slice<span class="op">.</span>get_unchecked_mut(i) <span class="op">+=</span> <span class="op">*</span>slice<span class="op">.</span>get_unchecked(j)<span class="op">;</span> <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></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> subscript_vector(<span class="kw">mut</span> vec<span class="op">:</span> <span class="dt">Vec</span><span class="op">&lt;</span><span class="dt">i32</span><span class="op">&gt;,</span> i<span class="op">:</span> <span class="dt">usize</span><span class="op">,</span> j<span class="op">:</span> <span class="dt">usize</span>) <span class="op">{</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">unsafe</span> <span class="op">{</span> <span class="op">*</span>vec<span class="op">.</span>get_unchecked_mut(i) <span class="op">+=</span> <span class="op">*</span>vec<span class="op">.</span>get_unchecked(j)<span class="op">;</span> <span class="op">}</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Rust’s unchecked subscript story is not elegant. You have to use the
separately named functions
<code class="sourceCode cpp">get_unchecked</code> and
<code class="sourceCode cpp">get_unchecked_mut</code>. These are unsafe
functions, so your calls have to be wrapped in <em>unsafe-blocks</em>.
That exposes other operations to the unsafe context. Since we’re
invoking functions directly, as opposed to using the
<code class="sourceCode cpp"><span class="op">[]</span></code> operator,
we don’t get automatic dereference of the returned borrows.</p>
<div class="sourceCode" id="cb30"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">+&gt;</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> vector</span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a>  value_type<span class="op">^</span> <span class="kw">operator</span><span class="op">[](</span>self<span class="op">^</span>, size_type i<span class="op">)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>i <span class="op">&gt;=</span> self<span class="op">.</span>size<span class="op">())</span> panic_bounds<span class="op">(</span><span class="st">&quot;vector subscript is out-of-bounds&quot;</span><span class="op">)</span>;</span>
<span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a>    unsafe <span class="op">{</span> <span class="cf">return</span> <span class="op">^</span>self<span class="op">.</span>data<span class="op">()[</span>i<span class="op">]</span>; <span class="op">}</span></span>
<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb30-8"><a href="#cb30-8" aria-hidden="true" tabindex="-1"></a>  value_type<span class="op">^</span> <span class="kw">operator</span><span class="op">[](</span>self<span class="op">^</span>, size_type i, no_runtime_check<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb30-9"><a href="#cb30-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">^</span>self<span class="op">.</span>data<span class="op">()[</span>i<span class="op">]</span>;</span>
<span id="cb30-10"><a href="#cb30-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb30-11"><a href="#cb30-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-12"><a href="#cb30-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> value_type<span class="op">^</span> <span class="kw">operator</span><span class="op">[](</span><span class="kw">const</span> self<span class="op">^</span>, size_type i<span class="op">)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb30-13"><a href="#cb30-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>i <span class="op">&gt;=</span> self<span class="op">.</span>size<span class="op">())</span> panic_bounds<span class="op">(</span><span class="st">&quot;vector subscript is out-of-bounds&quot;</span><span class="op">)</span>;</span>
<span id="cb30-14"><a href="#cb30-14" aria-hidden="true" tabindex="-1"></a>    unsafe <span class="op">{</span> <span class="cf">return</span> <span class="op">^</span>self<span class="op">.</span>data<span class="op">()[</span>i<span class="op">]</span>; <span class="op">}</span></span>
<span id="cb30-15"><a href="#cb30-15" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb30-16"><a href="#cb30-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> value_type<span class="op">^</span> <span class="kw">operator</span><span class="op">[](</span><span class="kw">const</span> self<span class="op">^</span>, size_type i, no_runtime_check<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb30-17"><a href="#cb30-17" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">^</span>self<span class="op">.</span>data<span class="op">()[</span>i<span class="op">]</span>;</span>
<span id="cb30-18"><a href="#cb30-18" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb30-19"><a href="#cb30-19" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span>
<span id="cb30-20"><a href="#cb30-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>The unsafe subscript works with user-defined types by introducing a
new library type <code class="sourceCode cpp">std2<span class="op">::</span>no_runtime_check</code>.
Append this as the last parameter in a user-defined <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">[]</span></code>
declaration, including multi-dimensional subscript operators, to enable
unsafe subscript binding. The compiler default-initializes a
<code class="sourceCode cpp">no_runtime_check</code> argument and
attempts to pass that during overload resolution. <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">[]</span></code>s
with <code class="sourceCode cpp">no_runtime_check</code> parameters are
<em>unsafe functions</em>, since they aren’t sound for all valid inputs.
However, when invoked as part of an unsafe subscript, they can still be
used in safe contexts. That’s because the user wrote the
<code class="sourceCode cpp">unsafe</code> token at the point of use,
exempting this function call from the unsafe check.</p>
<h2 data-number="2.2" id="borrow-checking"><span class="header-section-number">2.2</span> Borrow checking<a href="#borrow-checking" class="self-link"></a></h2>
<p>There’s one widely deployed solution to lifetime safety: garbage
collection. In GC, the scope of an object is extended as long as there
are live references to it. When there are no more live references, the
system is free to destroy the object. Most memory safe languages use
tracing garbage collection.<span class="citation" data-cites="tracing-gc">[<a href="https://en.wikipedia.org/wiki/Tracing_garbage_collection" role="doc-biblioref">tracing-gc</a>]</span> Some, like Python and Swift,
use automatic reference counting,<span class="citation" data-cites="arc">[<a href="https://docs.swift.org/swift-book/documentation/the-swift-programming-language/automaticreferencecounting/" role="doc-biblioref">arc</a>]</span> a flavor of garbage collection with
different tradeoffs.</p>
<p>Garbage collection requires storing objects on the <em>heap</em>. But
C++ is about <em>manual memory management</em>. We need to track
references to objects on the <em>stack</em> as well as on the heap. As
the stack unwinds objects are destroyed. We can’t extend their duration
beyond their lexical scopes. Borrow checking<span class="citation" data-cites="borrow-checking">[<a href="https://rust-lang.github.io/rfcs/2094-nll.html" role="doc-biblioref">borrow-checking</a>]</span> is a kind of
compile-time analysis that prevents using a reference after an object
has gone out of scope. That is, it solves use-after-free and iterator
invalidation bugs.</p>
<h3 data-number="2.2.1" id="use-after-free"><span class="header-section-number">2.2.1</span> Use-after-free<a href="#use-after-free" class="self-link"></a></h3>
<p><code class="sourceCode cpp">std<span class="op">::</span>string_view</code>
was added to C++17 as a safer alternative to passing character pointers
around. Unfortunately, its rvalue-reference constructor is so
dangerously designed that its reported to <em>encourage</em>
use-after-free bugs.<span class="citation" data-cites="string-view-use-after-free">[<a href="https://github.com/isocpp/CppCoreGuidelines/issues/1038" role="doc-biblioref">string-view-use-after-free</a>]</span></p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/string_view0.cxx"><strong>string_view0.cxx</strong></a>
– <a href="https://godbolt.org/z/e3TG6W5Me">(Compiler Explorer)</a></p>
<div class="sourceCode" id="cb31"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;iostream&gt;</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;string&gt;</span></span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;string_view&gt;</span></span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>string s <span class="op">=</span> <span class="st">&quot;Hellooooooooooooooo &quot;</span>;</span>
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>string_view sv <span class="op">=</span> s <span class="op">+</span> <span class="st">&quot;World</span><span class="sc">\n</span><span class="st">&quot;</span>;</span>
<span id="cb31-8"><a href="#cb31-8" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> sv;</span>
<span id="cb31-9"><a href="#cb31-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb3"><pre class="sourceCode txt"><code class="sourceCode default"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>$ circle string_view0.cxx</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>$ ./string_view</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a> ��:��  �ooo World</span></code></pre></div>
<p><code class="sourceCode cpp">s</code> is initialized with a long
string, bypassing the short-string optimization and storing it on the
heap. The <code class="sourceCode cpp">string<span class="op">::</span><span class="kw">operator</span><span class="op">+</span></code>
returns a temporary
<code class="sourceCode cpp">std<span class="op">::</span>string</code>
object, also with its data on the heap.
<code class="sourceCode cpp">sv</code> is initialized by calling the
<code class="sourceCode cpp">string<span class="op">::</span><span class="kw">operator</span> string_view<span class="op">()</span></code>
conversion function on the temporary. The temporary string goes out of
scope at the end of that statement, its storage is returned to the heap,
and the user prints a string view with dangling pointers!</p>
<p>This design is full of sharp edges. It should not have made the ISO
Standard, but C++ as a language doesn’t provide great alternatives.
Borrow checking is the technology that flags these problems. Safe C++
provides a lifetime-aware
<code class="sourceCode cpp">string_view</code> that ends the risk of
dangling views.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/string_view1.cxx"><strong>string_view1.cxx</strong></a>
– <a href="https://godbolt.org/z/1M6hMv43M">(Compiler Explorer)</a></p>
<div class="sourceCode" id="cb32"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;std2.h&gt;</span></span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a>  std2<span class="op">::</span>string s<span class="op">(</span><span class="st">&quot;Hellooooooooooooooo &quot;</span><span class="op">)</span>;</span>
<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a>  std2<span class="op">::</span>string_view sv <span class="op">=</span> s <span class="op">+</span> <span class="st">&quot;World</span><span class="sc">\n</span><span class="st">&quot;</span>;</span>
<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a>  println<span class="op">(</span>sv<span class="op">)</span>;</span>
<span id="cb32-8"><a href="#cb32-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb4"><pre class="sourceCode txt"><code class="sourceCode default"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>$ circle string_view1.cxx -I ../libsafecxx/single-header/</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>safety: during safety checking of int main() safe</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  borrow checking: string_view1.cxx:7:11</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    println(sv); </span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>            ^</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>  use of sv depends on expired loan</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>  drop of temporary object std2::string between its shared borrow and its use</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>  loan created at string_view1.cxx:6:28</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>    std2::string_view sv = s + &quot;World\n&quot;; </span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>                             ^</span></code></pre></div>
<p>The compiler flags the use of the dangling view: <code class="sourceCode cpp">println<span class="op">(</span>sv<span class="op">)</span></code>.
It marks the invalidating action: the drop of the temporary string. And
it indicates where the loan was created: the conversion to
<code class="sourceCode cpp">string_view</code> right after the string
concatenation. See the <a href="#lifetime-error-reporting">error
reporting</a> section for details on lifetime diagnostics.</p>
<p>The lifetime mechanics are evident from the declaration of the
conversion function on
<code class="sourceCode cpp">std2<span class="op">::</span>string</code>
which produces a <code class="sourceCode cpp">std2<span class="op">::</span>string_view</code>.
This is gets called during <code class="sourceCode cpp">sv</code>’s
initialization.</p>
<div class="sourceCode" id="cb33"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> basic_string_view<span class="op">/(</span>a<span class="op">)</span> <span class="op">{</span></span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a>  basic_string_view<span class="op">(</span><span class="kw">const</span> <span class="op">[</span>value_type; dyn<span class="op">]^/</span>a str, no_utf_check<span class="op">)</span> <span class="kw">noexcept</span></span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> p_<span class="op">(</span>str<span class="op">)</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb33-5"><a href="#cb33-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb33-6"><a href="#cb33-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-7"><a href="#cb33-7" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> basic_string <span class="op">{</span></span>
<span id="cb33-8"><a href="#cb33-8" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb33-9"><a href="#cb33-9" aria-hidden="true" tabindex="-1"></a>  basic_string_view<span class="op">&lt;</span>value_type<span class="op">&gt;</span> str<span class="op">(</span>self <span class="kw">const</span><span class="op">^)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb33-10"><a href="#cb33-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> no_utf_check <span class="op">=</span> <span class="kw">typename</span> basic_string_view<span class="op">&lt;</span>value_type<span class="op">&gt;::</span>no_utf_check;</span>
<span id="cb33-11"><a href="#cb33-11" aria-hidden="true" tabindex="-1"></a>    unsafe <span class="op">{</span> <span class="cf">return</span> basic_string_view<span class="op">&lt;</span>value_type<span class="op">&gt;(</span>self<span class="op">.</span>slice<span class="op">()</span>, no_utf_check<span class="op">{})</span>; <span class="op">}</span></span>
<span id="cb33-12"><a href="#cb33-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb33-13"><a href="#cb33-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-14"><a href="#cb33-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">operator</span> basic_string_view<span class="op">&lt;</span>value_type<span class="op">&gt;(</span>self <span class="kw">const</span><span class="op">^)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb33-15"><a href="#cb33-15" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> self<span class="op">.</span>str<span class="op">()</span>;</span>
<span id="cb33-16"><a href="#cb33-16" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb33-17"><a href="#cb33-17" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span>
<span id="cb33-18"><a href="#cb33-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>String concatenation forms a temporary string. The temporary string
doesn’t have any lifetime parameters. It owns its data and has <em>value
semantics</em>. We form a <code class="sourceCode cpp">std2<span class="op">::</span>string_view</code>
from the temporary string.
<code class="sourceCode cpp">basic_string_view</code> declares a named
lifetime parameter,
<code class="sourceCode cpp"><span class="op">/</span>a</code>, which
models the lifetime of of the view. The view has <em>reference
semantics</em>, and it needs a lifetime for the purpose of live
analysis. The lifetime of this view will originate with a loan on a
string, which owns the data, and is kept live when using the view.
Mutating or dropping the string while there’s a live loan on it makes
the program ill-formed. This is how borrow checking protects against
use-after-free errors. Keep in mind that the lifetime parameter is part
of the <em>view</em>, not part of the data it refers to.</p>
<p>Initializing <code class="sourceCode cpp">sv</code> invokes the
conversion function on that temporary. The conversion function
<em>borrows</em> self, creating a <em>loan</em> the temporary. The
lifetime argument isn’t spelled out in the conversion function’s
declaration; rather, it’s assigned during lifetime elision, which is
part of <a href="#lifetime-normalization">normalization</a>. The return
type of the conversion function is a
<code class="sourceCode cpp">string_view</code>. Since
<code class="sourceCode cpp">string_view</code> is a lifetime binder,
elision invents a lifetime argument for the return type and constrains
the lifetime of the <code class="sourceCode cpp">self</code> reference
to outlive it. This is all established in the declaration. Callers don’t
look inside function definitions during borrow checking. Both the caller
and callee agree on the function’s lifetime contracts, entirely from
information in the function declaration. This establishes a chain of
constraints that relate all uses of a reference back to its original
loan.</p>
<p>The <code class="sourceCode cpp">str</code> accessor provides the
implementation. It constructs a
<code class="sourceCode cpp">basic_string_view</code> and bypasses the
runtime UTF-8 check by passing a
<code class="sourceCode cpp">no_utf_check</code> argument. Like Rust,
Safe C++ strings guarantee their contents are well-formed UNICODE code
points.</p>
<p>When we go to print the view, the compiler raises a use-after-free
error. The call to <code class="sourceCode cpp">println</code>
<em>uses</em> the lifetime arguments associated with the function
argument <code class="sourceCode cpp">sv</code>. Middle-end analysis
solves the <a href="#systems-of-constraints">constraint equation</a>,
and puts the original loan on the string temporary object <em>in
scope</em> at all program points between the string concatenation and
the <code class="sourceCode cpp">println</code> call. The borrow checker
pass looks for invalidating actions on places that overloap in-scope
loans. There’s a drop of the temporary string at the end of the full
expression containing the string concatenation. This isn’t anything
special to Safe C++, this is ordinary RAII cleanup of objects as they
fall out of lexical scope. The drop is a kind of <em>shallow write</em>,
and it invalidates the shared borrow taken on the temporary when its
conversion operator to <code class="sourceCode cpp">string_view</code>
was called.</p>
<p>Unlike previous attempts at lifetime safety<span class="citation" data-cites="P1179R1">[<a href="https://wg21.link/p1179r1" role="doc-biblioref">P1179R1</a>]</span>, borrow checking is absolutely
robust. It does not rely on heuristics that can fail. It allows for any
distance between the use of a borrow and an invalidating action on an
originating loan, with any amount of complex control flow between. MIR
analysis will solve the constraint equation, run the borrow checker, and
issue a diagnostic.</p>
<h3 data-number="2.2.2" id="iterator-invalidation"><span class="header-section-number">2.2.2</span> Iterator invalidation<a href="#iterator-invalidation" class="self-link"></a></h3>
<p>Let’s take a closer look at the iterator invalidation example.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/iterator.cxx"><strong>iterator.cxx</strong></a>
– <a href="https://godbolt.org/z/vneosEGrK">(Compiler Explorer)</a></p>
<div class="sourceCode" id="cb34"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;std2.h&gt;</span></span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb34-5"><a href="#cb34-5" aria-hidden="true" tabindex="-1"></a>  std2<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> vec <span class="op">{</span> <span class="dv">11</span>, <span class="dv">15</span>, <span class="dv">20</span> <span class="op">}</span>;</span>
<span id="cb34-6"><a href="#cb34-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-7"><a href="#cb34-7" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span><span class="op">(</span><span class="dt">int</span> x <span class="op">:</span> vec<span class="op">)</span> <span class="op">{</span></span>
<span id="cb34-8"><a href="#cb34-8" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Ill-formed. mutate of vec invalidates iterator in ranged-for.</span></span>
<span id="cb34-9"><a href="#cb34-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span><span class="op">(</span>x <span class="op">%</span> <span class="dv">2</span><span class="op">)</span></span>
<span id="cb34-10"><a href="#cb34-10" aria-hidden="true" tabindex="-1"></a>      mut vec<span class="op">.</span>push_back<span class="op">(</span>x<span class="op">)</span>;</span>
<span id="cb34-11"><a href="#cb34-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-12"><a href="#cb34-12" aria-hidden="true" tabindex="-1"></a>    std2<span class="op">::</span>println<span class="op">(</span>x<span class="op">)</span>;</span>
<span id="cb34-13"><a href="#cb34-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb34-14"><a href="#cb34-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb5"><pre class="sourceCode txt"><code class="sourceCode default"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>$ circle iterator.cxx -I ../libsafecxx/single-header/</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>safety: during safety checking of int main() safe</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>  borrow checking: iterator.cxx:10:11</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>        mut vec.push_back(x);</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>            ^</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>  mutable borrow of vec between its shared borrow and its use</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>  loan created at iterator.cxx:7:15</span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>    for(int x : vec) {</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>                ^</span></code></pre></div>
<p>The <em>ranged-for</em> creates an iterator on the vector. The
iterator stays initialized for the whole duration of the loop. This puts
a shared borrow on <code class="sourceCode cpp">vec</code>, because the
iterator provides read-only access to that container. Inside the loop,
we mutate the container. The <code class="sourceCode cpp">mut</code>
keyword enters the <a href="#the-mutable-context">mutable context</a>
which enables binding mutable borrows to lvalues in the standard
conversion during overload resolution for the
<code class="sourceCode cpp">push_back</code> call. Now there’s a shared
borrow that’s live, for the iterator, and a mutable borrow that’s live,
for the <code class="sourceCode cpp">push_back</code>. That violates
exclusivity and the borrow checker raises an error.</p>
<p>To users, iterator invalidation looks like a different phenomenon
than the use-after-free defect in the previous section. But to the
compiler, and hopefully to library authors, they can be reasoned about
similarly, as they’re both borrow checker violations.</p>
<blockquote>
<p>The static analysis based on the proposed lifetime annotations cannot
catch all memory safety problems in C++ code. Specifically, it cannot
catch all temporal memory safety bugs (for example, ones caused by
iterator invalidation), and of course lifetime annotations don’t help
with spatial memory safety (for example, indexing C-style arrays out of
bounds). See the comparison with Rust below for a detailed
discussion.</p>
<p>– <cite>[RFC] Lifetime annotations for C++ Clang Frontend</cite><span class="citation" data-cites="clang-lifetime-annotations">[<a href="https://discourse.llvm.org/t/rfc-lifetime-annotations-for-c/61377" role="doc-biblioref">clang-lifetime-annotations</a>]</span></p>
</blockquote>
<p>Clang’s lifetime annotations project doesn’t implement borrow
checking. For that project, iterator invalidation is out of scope,
because it really is a different phenomenon than the lifetime tracking
<em>heuristics</em> employed in detecting other use-after-free
defects.</p>
<div class="sourceCode" id="cb35"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a>interface iterator <span class="op">{</span></span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">typename</span> item_type;</span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a>  optional<span class="op">&lt;</span>item_type<span class="op">&gt;</span> next<span class="op">(</span>self<span class="op">^)</span> safe;</span>
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb35-5"><a href="#cb35-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-6"><a href="#cb35-6" aria-hidden="true" tabindex="-1"></a>interface make_iter <span class="op">{</span></span>
<span id="cb35-7"><a href="#cb35-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">typename</span> iter_type;</span>
<span id="cb35-8"><a href="#cb35-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">typename</span> iter_mut_type;</span>
<span id="cb35-9"><a href="#cb35-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">typename</span> into_iter_type;</span>
<span id="cb35-10"><a href="#cb35-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-11"><a href="#cb35-11" aria-hidden="true" tabindex="-1"></a>  iter_type      iter<span class="op">(</span><span class="kw">const</span> self<span class="op">^)</span> safe;</span>
<span id="cb35-12"><a href="#cb35-12" aria-hidden="true" tabindex="-1"></a>  iter_mut_type  iter<span class="op">(</span>self<span class="op">^)</span> safe;</span>
<span id="cb35-13"><a href="#cb35-13" aria-hidden="true" tabindex="-1"></a>  into_iter_type iter<span class="op">(</span>self<span class="op">)</span> safe;</span>
<span id="cb35-14"><a href="#cb35-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb35-15"><a href="#cb35-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-16"><a href="#cb35-16" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb35-17"><a href="#cb35-17" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> slice_iterator<span class="op">/(</span>a<span class="op">)</span>;</span>
<span id="cb35-18"><a href="#cb35-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-19"><a href="#cb35-19" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb35-20"><a href="#cb35-20" aria-hidden="true" tabindex="-1"></a>impl vector<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">:</span> make_iter <span class="op">{</span></span>
<span id="cb35-21"><a href="#cb35-21" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> iter_type <span class="op">=</span> slice_iterator<span class="op">&lt;</span>T <span class="kw">const</span><span class="op">&gt;</span>;</span>
<span id="cb35-22"><a href="#cb35-22" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> iter_mut_type <span class="op">=</span> slice_iterator<span class="op">&lt;</span>T<span class="op">&gt;</span>;</span>
<span id="cb35-23"><a href="#cb35-23" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> into_iter_type  <span class="op">=</span> into_iterator<span class="op">&lt;</span>T<span class="op">&gt;</span>;</span>
<span id="cb35-24"><a href="#cb35-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-25"><a href="#cb35-25" aria-hidden="true" tabindex="-1"></a>  iter_type iter<span class="op">(</span>self <span class="kw">const</span><span class="op">^)</span> <span class="kw">noexcept</span> safe <span class="kw">override</span> <span class="op">{</span></span>
<span id="cb35-26"><a href="#cb35-26" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> slice_iterator<span class="op">&lt;</span><span class="kw">const</span> T<span class="op">&gt;(</span>self<span class="op">.</span>slice<span class="op">())</span>;</span>
<span id="cb35-27"><a href="#cb35-27" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb35-28"><a href="#cb35-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-29"><a href="#cb35-29" aria-hidden="true" tabindex="-1"></a>  iter_mut_type iter<span class="op">(</span>self<span class="op">^)</span> <span class="kw">noexcept</span> safe <span class="kw">override</span> <span class="op">{</span></span>
<span id="cb35-30"><a href="#cb35-30" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> slice_iterator<span class="op">&lt;</span>T<span class="op">&gt;(</span>self<span class="op">.</span>slice<span class="op">())</span>;</span>
<span id="cb35-31"><a href="#cb35-31" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb35-32"><a href="#cb35-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-33"><a href="#cb35-33" aria-hidden="true" tabindex="-1"></a>  into_iter_type iter<span class="op">(</span>self<span class="op">)</span> <span class="kw">noexcept</span> safe <span class="kw">override</span> <span class="op">{</span></span>
<span id="cb35-34"><a href="#cb35-34" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> p <span class="op">=</span> self<span class="op">^.</span>data<span class="op">()</span>;</span>
<span id="cb35-35"><a href="#cb35-35" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> len <span class="op">=</span> self<span class="op">.</span>size<span class="op">()</span>;</span>
<span id="cb35-36"><a href="#cb35-36" aria-hidden="true" tabindex="-1"></a>    forget<span class="op">(</span>rel self<span class="op">)</span>;</span>
<span id="cb35-37"><a href="#cb35-37" aria-hidden="true" tabindex="-1"></a>    unsafe <span class="op">{</span> <span class="cf">return</span> into_iter_type<span class="op">(</span>p, p <span class="op">+</span> len<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb35-38"><a href="#cb35-38" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb35-39"><a href="#cb35-39" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>To opt into safe ranged-for iteration, containers implement the <code class="sourceCode cpp">std2<span class="op">::</span>make_iter</code>
interface. They can provide const iterators, mutable iterators or
<em>consuming iterators</em> which take ownership of the operand’s data
and destroy its container in the process.</p>
<p>Because the <em>range-initializer</em> of the loop is an lvalue of
<code class="sourceCode cpp">vector</code> that’s outside the mutable
context, the const iterator overload of <code class="sourceCode cpp">vector<span class="op">&lt;</span>T<span class="op">&gt;::</span>iter</code>
gets chosen. That returns an <code class="sourceCode cpp">std2<span class="op">::</span>slice_iterator<span class="op">&lt;</span>T <span class="kw">const</span><span class="op">&gt;</span></code>
into the vector’s contents. Here’s the first borrow: lifetime elision
invents a lifetime parameter for the <code class="sourceCode cpp">self <span class="kw">const</span><span class="op">^</span></code>
parameter, which is also used for the named lifetime argument
<code class="sourceCode cpp"><span class="op">/</span>a</code> of the
<code class="sourceCode cpp">slice_iterator</code> return type. As with
the use-after-free example, the <code class="sourceCode cpp">vector<span class="op">&lt;</span>T<span class="op">&gt;::</span>iter</code>
function declaration establishes an <em>outlives-constraint</em>: the
lifetime on the <code class="sourceCode cpp">self <span class="kw">const</span><span class="op">^</span></code>
operand must outlive the lifetime on the result object.</p>
<div class="sourceCode" id="cb36"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> slice_iterator<span class="op">/(</span>a<span class="op">)</span></span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb36-4"><a href="#cb36-4" aria-hidden="true" tabindex="-1"></a>  T<span class="op">*</span> unsafe p_;</span>
<span id="cb36-5"><a href="#cb36-5" aria-hidden="true" tabindex="-1"></a>  T<span class="op">*</span> end_;</span>
<span id="cb36-6"><a href="#cb36-6" aria-hidden="true" tabindex="-1"></a>  T<span class="op">^/</span>a __phantom_data;</span>
<span id="cb36-7"><a href="#cb36-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-8"><a href="#cb36-8" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb36-9"><a href="#cb36-9" aria-hidden="true" tabindex="-1"></a>  slice_iterator<span class="op">([</span>T; dyn<span class="op">]^/</span>a s<span class="op">)</span> <span class="kw">noexcept</span> safe</span>
<span id="cb36-10"><a href="#cb36-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> p_<span class="op">((*</span>s<span class="op">)~</span>as_pointer<span class="op">)</span>, unsafe end_<span class="op">((*</span>s<span class="op">)~</span>as_pointer <span class="op">+</span> <span class="op">(*</span>s<span class="op">)~</span>length<span class="op">)</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb36-11"><a href="#cb36-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-12"><a href="#cb36-12" aria-hidden="true" tabindex="-1"></a>  optional<span class="op">&lt;</span>T<span class="op">^/</span>a<span class="op">&gt;</span> next<span class="op">(</span>self<span class="op">^)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb36-13"><a href="#cb36-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>self<span class="op">-&gt;</span>p_ <span class="op">==</span> self<span class="op">-&gt;</span>end_<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">.</span>none; <span class="op">}</span></span>
<span id="cb36-14"><a href="#cb36-14" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">.</span>some<span class="op">(^*</span>self<span class="op">-&gt;</span>p_<span class="op">++)</span>;</span>
<span id="cb36-15"><a href="#cb36-15" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb36-16"><a href="#cb36-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>The compiler drains the iterator by calling
<code class="sourceCode cpp">next</code> until the <code class="sourceCode cpp">std2<span class="op">::</span>optional</code> it
returns is
<code class="sourceCode cpp"><span class="op">.</span>none</code>. Each
in-range invocation of <code class="sourceCode cpp">slice_iterator<span class="op">::</span>next</code>
forms a borrow to the current element and advances
<code class="sourceCode cpp">p_</code> to the next element.
<code class="sourceCode cpp">next</code>’s object parameter is written
<code class="sourceCode cpp">self<span class="op">^</span></code>, an
abbreviated form of <code class="sourceCode cpp">slice_iterator<span class="op">/</span>a<span class="op">^</span> self</code>.
The borrow returned in <code class="sourceCode cpp">optional<span class="op">&lt;</span>T<span class="op">^/</span>a<span class="op">&gt;</span></code>
is outlived by the implied lifetime of the
<code class="sourceCode cpp">self</code> parameter. This transitively
means that the underlying <code class="sourceCode cpp">vector</code>
must outlive the reference in the
<code class="sourceCode cpp">optional</code> returned from <code class="sourceCode cpp">slice_iterator<span class="op">::</span>next</code>.
All these lifetime constraints feed the <a href="#systems-of-constraints">constraint equation</a> to enable
inter-procedural live analysis.</p>
<p>It’s the periodic call into <code class="sourceCode cpp">next</code>
that keeps the original borrow on
<code class="sourceCode cpp">vec</code> live. Even though the use of
<code class="sourceCode cpp">next</code> is lexically before the
<code class="sourceCode cpp">push_back</code> (it’s at the top of the
loop, rather than inside the loop), control flow analysis shows that
it’s also <em>downstream</em> of the push_back. MIR analysis follows the
backedge from the end of the body of the loop back to its start. That
establishes the liveness of the shared borrow on
<code class="sourceCode cpp">vec</code>.</p>
<div class="sourceCode" id="cb37"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">+&gt;</span></span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> vector <span class="op">{</span></span>
<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> push_back<span class="op">(</span>self<span class="op">^</span>, T t<span class="op">)</span> safe <span class="op">{</span></span>
<span id="cb37-4"><a href="#cb37-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>self<span class="op">.</span>capacity<span class="op">()</span> <span class="op">==</span> self<span class="op">.</span>size<span class="op">())</span> <span class="op">{</span> self<span class="op">.</span>grow<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb37-5"><a href="#cb37-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-6"><a href="#cb37-6" aria-hidden="true" tabindex="-1"></a>    __rel_write<span class="op">(</span>self<span class="op">-&gt;</span>p_ <span class="op">+</span> self<span class="op">-&gt;</span>size_, rel t<span class="op">)</span>;</span>
<span id="cb37-7"><a href="#cb37-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">++</span>self<span class="op">-&gt;</span>size_;</span>
<span id="cb37-8"><a href="#cb37-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb37-9"><a href="#cb37-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span>
<span id="cb37-10"><a href="#cb37-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>The user enters the mutable context with the
<code class="sourceCode cpp">mut</code> token and calls
<code class="sourceCode cpp">push_back</code>. This enables binding a
mutable borrow to <code class="sourceCode cpp">vec</code> in a standard
conversion during overload resolution to
<code class="sourceCode cpp">push_back</code>. Since the shared borrow
that was taken to produce
<code class="sourceCode cpp">slice_iterator</code> is still in scope,
the new mutable borrow violates exclusivity and the program is
ill-formed.</p>
<p>Borrow checking is attractive because it’s a unified treatment for
enforcing dependencies. Compiler engineers aren’t asked to develop some
heuristics for use-after-free, different ones for iterator invalidation,
and still more clever ones for thread safety. Developers simply use the
borrow types and the compiler enforces the attendant constraints.</p>
<h3 data-number="2.2.3" id="initializer-lists"><span class="header-section-number">2.2.3</span> Initializer lists<a href="#initializer-lists" class="self-link"></a></h3>
<p>Almost every part of the C++ Standard Library will exhibit unsound
behavior even when used in benign-looking ways. Much of it was designed
without consideration of memory safety. This goes even to the most core
types, like <code class="sourceCode cpp">std<span class="op">::</span>initializer_list</code>.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/initlist0.cxx"><strong>initlist0.cxx</strong></a></p>
<div class="sourceCode" id="cb38"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;vector&gt;</span></span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;string_view&gt;</span></span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;iostream&gt;</span></span>
<span id="cb38-4"><a href="#cb38-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-5"><a href="#cb38-5" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> <span class="kw">namespace</span> std;</span>
<span id="cb38-6"><a href="#cb38-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-7"><a href="#cb38-7" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb38-8"><a href="#cb38-8" aria-hidden="true" tabindex="-1"></a>  initializer_list<span class="op">&lt;</span>string_view<span class="op">&gt;</span> initlist1;</span>
<span id="cb38-9"><a href="#cb38-9" aria-hidden="true" tabindex="-1"></a>  initializer_list<span class="op">&lt;</span>string_view<span class="op">&gt;</span> initlist2;</span>
<span id="cb38-10"><a href="#cb38-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-11"><a href="#cb38-11" aria-hidden="true" tabindex="-1"></a>  string s <span class="op">=</span> <span class="st">&quot;Hello&quot;</span>;</span>
<span id="cb38-12"><a href="#cb38-12" aria-hidden="true" tabindex="-1"></a>  string t <span class="op">=</span> <span class="st">&quot;World&quot;</span>;</span>
<span id="cb38-13"><a href="#cb38-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-14"><a href="#cb38-14" aria-hidden="true" tabindex="-1"></a>  <span class="co">// initializer lists holds dangling pointers into backing array.</span></span>
<span id="cb38-15"><a href="#cb38-15" aria-hidden="true" tabindex="-1"></a>  initlist1 <span class="op">=</span> <span class="op">{</span> s, s, s, s <span class="op">}</span>;</span>
<span id="cb38-16"><a href="#cb38-16" aria-hidden="true" tabindex="-1"></a>  initlist2 <span class="op">=</span> <span class="op">{</span> t, t, t, t <span class="op">}</span>;</span>
<span id="cb38-17"><a href="#cb38-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-18"><a href="#cb38-18" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Prints like normal.</span></span>
<span id="cb38-19"><a href="#cb38-19" aria-hidden="true" tabindex="-1"></a>  vector<span class="op">&lt;</span>string_view<span class="op">&gt;</span> vec<span class="op">(</span>initlist1<span class="op">)</span>;</span>
<span id="cb38-20"><a href="#cb38-20" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span><span class="op">(</span>string_view sv <span class="op">:</span> vec<span class="op">)</span></span>
<span id="cb38-21"><a href="#cb38-21" aria-hidden="true" tabindex="-1"></a>    cout<span class="op">&lt;&lt;</span> sv<span class="op">&lt;&lt;</span> <span class="st">&quot;</span><span class="sc">\n</span><span class="st">&quot;</span>;</span>
<span id="cb38-22"><a href="#cb38-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-23"><a href="#cb38-23" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Catastrophe.</span></span>
<span id="cb38-24"><a href="#cb38-24" aria-hidden="true" tabindex="-1"></a>  vec <span class="op">=</span> initlist2;</span>
<span id="cb38-25"><a href="#cb38-25" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span><span class="op">(</span>string_view sv <span class="op">:</span> vec<span class="op">)</span></span>
<span id="cb38-26"><a href="#cb38-26" aria-hidden="true" tabindex="-1"></a>    cout<span class="op">&lt;&lt;</span> sv<span class="op">&lt;&lt;</span> <span class="st">&quot;</span><span class="sc">\n</span><span class="st">&quot;</span>;</span>
<span id="cb38-27"><a href="#cb38-27" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb39"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a>$ clang++ initlist0.cxx -o initlist0 -stdlib=libc++ -O2</span>
<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a>$ ./initlist0</span>
<span id="cb39-3"><a href="#cb39-3" aria-hidden="true" tabindex="-1"></a>Hello</span>
<span id="cb39-4"><a href="#cb39-4" aria-hidden="true" tabindex="-1"></a>Hello</span>
<span id="cb39-5"><a href="#cb39-5" aria-hidden="true" tabindex="-1"></a>Hello</span>
<span id="cb39-6"><a href="#cb39-6" aria-hidden="true" tabindex="-1"></a>Hello</span>
<span id="cb39-7"><a href="#cb39-7" aria-hidden="true" tabindex="-1"></a>__cxa_guard_release%s failed to broadcast__cxa_guard_abortunexpected_handler une</span>
<span id="cb39-8"><a href="#cb39-8" aria-hidden="true" tabindex="-1"></a>xpectedly returnedterminate_handler unexpectedly returnedterminate_handler unexp</span>
<span id="cb39-9"><a href="#cb39-9" aria-hidden="true" tabindex="-1"></a>ectedly threw an exceptionPure virtual function called!Deleted virtual function</span>
<span id="cb39-10"><a href="#cb39-10" aria-hidden="true" tabindex="-1"></a>called!std::exceptionstd::bad_exceptionstd::bad_allocbad_array_new_lengthSt9exce</span>
<span id="cb39-11"><a href="#cb39-11" aria-hidden="true" tabindex="-1"></a>ptionSt13bad_exceptionSt20bad_array_new_lengthSt9bad_alloc�a���a��b��b��0b��St12</span>
<span id="cb39-12"><a href="#cb39-12" aria-hidden="true" tabindex="-1"></a>domain_errorSt11logic_errorSt16invalid_argumentSt12length_errorSt12out_of_rangeS</span>
<span id="cb39-13"><a href="#cb39-13" aria-hidden="true" tabindex="-1"></a>t11range_errorSt13runtime_errorSt14overflow_errorSt15underflow_errorstd::bad_cas</span>
<span id="cb39-14"><a href="#cb39-14" aria-hidden="true" tabindex="-1"></a>tstd::bad_typeidSt9type_infoSt8bad_castSt10bad_typeidlibc++abi: reinterpret_cast</span>
<span id="cb39-15"><a href="#cb39-15" aria-hidden="true" tabindex="-1"></a>&lt;size_t&gt;(p + 1) % RequiredAlignment == 0/home/sean/projects/llvm-new/libcxxabi/s</span>
<span id="cb39-16"><a href="#cb39-16" aria-hidden="true" tabindex="-1"></a>rc/fallback_malloc.cppvoid *(anonymous namespace)::fallback_malloc(size_t)reinte</span>
<span id="cb39-17"><a href="#cb39-17" aria-hidden="true" tabindex="-1"></a>rpret_cast&lt;size_t&gt;(ptr) % RequiredAlignment == 0N10__cxxabiv116__shim_type_infoE</span>
<span id="cb39-18"><a href="#cb39-18" aria-hidden="true" tabindex="-1"></a>N10__cxxabiv117__class_type_infoEN10__cxxabiv117__pbase_type_infoEN10__cxxabiv11</span>
<span id="cb39-19"><a href="#cb39-19" aria-hidden="true" tabindex="-1"></a>9__pointer_type_infoE</span></code></pre></div>
<p>This example declares two initializer lists of string views,
<code class="sourceCode cpp">initlist1</code> and
<code class="sourceCode cpp">initlist2</code>. It declares two strings
objects and assigns views of the strings into those initializer lists.
Printing their contents is undefined behavior. It may go undetected. But
compiling with <code class="sourceCode cpp">clang<span class="op">++</span> <span class="op">-</span>O2</code>
and targeting libc++ manifests the defect: the program is printing
uncontrollably from some arbitrary place in memory. This is the kind of
safety defect that the NSA and corporate researchers have been warning
industry about.</p>
<p>The defect is perplexing because the string objects
<code class="sourceCode cpp">s</code> and
<code class="sourceCode cpp">t</code> <em>are still in scope</em>! This
is a use-after-free bug, but not with any object that the user declared.
It’s a use-after-free of implicit backing stores that C++ generates when
lowering initializer list expressions.</p>
<div class="sourceCode" id="cb40"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a>  <span class="co">// initializer lists holds dangling pointers into backing array.</span></span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a>  initlist1 <span class="op">=</span> <span class="op">{</span> s, s, s, s <span class="op">}</span>;</span>
<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a>  initlist2 <span class="op">=</span> <span class="op">{</span> t, t, t, t <span class="op">}</span>;</span></code></pre></div>
<p>Each initializer list expression provisions a 4-element array of
<code class="sourceCode cpp">string_view</code> as a backing store. An
initializer list object is simply a pointer into the array and a length.
It’s the pointer into the backing store that’s copied into
<code class="sourceCode cpp">initlist1</code> and
<code class="sourceCode cpp">initlist2</code>. At the end of each full
expression, those backing stores fall out of scope, leaving dangling
pointers in the initializer lists that the user declared. When compiled
with aggressive local storage optimizations, the stack space that hosted
the backing store for <code class="sourceCode cpp"><span class="op">{</span> t, t, t, t <span class="op">}</span></code>
gets reused for other objects. Some subsequent initialization overwrites
the pointer and length fields of the string views in that reclaimed
backing store. Printing from the
<code class="sourceCode cpp">initlist2</code> declaration prints from
the smashed pointers.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/initlist1.cxx"><strong>initlist1.cxx</strong></a>
– <a href="https://godbolt.org/z/xxdTfdh1d">(Compiler Explorer)</a></p>
<div class="sourceCode" id="cb6"><pre class="sourceCode cxx"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;std2.h&gt;</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> <span class="kw">namespace</span> std2<span class="op">;</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>  initializer_list<span class="op">&lt;</span>string_view<span class="op">&gt;</span> initlist<span class="op">;</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>  string s<span class="op">{</span><span class="st">&quot;Hello&quot;</span><span class="op">};</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>  string t<span class="op">{</span><span class="st">&quot;World&quot;</span><span class="op">};</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>  <span class="co">// initializer lists holds dangling pointers into backing array.</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>  initlist <span class="op">=</span> <span class="op">{</span> s<span class="op">,</span> t<span class="op">,</span> s<span class="op">,</span> t <span class="op">};</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Borrow checker error. `use of initlist depends on expired loan`</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a>  vector<span class="op">&lt;</span>string_view<span class="op">&gt;</span> vec<span class="op">(</span>rel initlist<span class="op">);</span></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span><span class="op">(</span>string_view sv <span class="op">:</span> vec<span class="op">)</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a>    println<span class="op">(</span>sv<span class="op">);</span></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb41"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a>$ circle initlist1.cxx -I ../libsafecxx/single-header/</span>
<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a>safety: during safety checking of int main() safe</span>
<span id="cb41-3"><a href="#cb41-3" aria-hidden="true" tabindex="-1"></a>  borrow checking: initlist1.cxx:16:31</span>
<span id="cb41-4"><a href="#cb41-4" aria-hidden="true" tabindex="-1"></a>    vector&lt;string_view&gt; vec(rel initlist);</span>
<span id="cb41-5"><a href="#cb41-5" aria-hidden="true" tabindex="-1"></a>                                ^</span>
<span id="cb41-6"><a href="#cb41-6" aria-hidden="true" tabindex="-1"></a>  use of initlist depends on expired loan</span>
<span id="cb41-7"><a href="#cb41-7" aria-hidden="true" tabindex="-1"></a>  drop of temporary object std2::string_view[4] while mutable borrow of</span>
<span id="cb41-8"><a href="#cb41-8" aria-hidden="true" tabindex="-1"></a>    temporary object std2::string_view[4][..] is in scope</span>
<span id="cb41-9"><a href="#cb41-9" aria-hidden="true" tabindex="-1"></a>  loan created at initlist1.cxx:13:14</span>
<span id="cb41-10"><a href="#cb41-10" aria-hidden="true" tabindex="-1"></a>    initlist = { s, t, s, t };</span>
<span id="cb41-11"><a href="#cb41-11" aria-hidden="true" tabindex="-1"></a>               ^</span></code></pre></div>
<p>Safe C++ includes a new <code class="sourceCode cpp">std2<span class="op">::</span>initializer_list</code>
which sits side-by-side with the legacy type. The compiler provisions a
backing store to hold the data, and the new initializer list also keeps
pointers into that. The backing store expires at the end of the
assignment state. But borrow checking prevents the use-after-free defect
that troubles <code class="sourceCode cpp">std<span class="op">::</span>initializer_list</code>.
An error is filed where the initializer list constructs a vector: <code class="sourceCode cpp">use of initlist depends on expired loan</code>.</p>
<p>The Safe C++ replacement for initializer lists takes the
<em>ownership and borrowing</em> model to heart by both owning and
borrowing. It borrows the storage its elements are held in, but it also
owns the elements and calls their destructors. We want to support
relocation out of the initializer list. That means the backing store
doesn’t call the element destructors, because those elements may have
been relocated out by the user. <code class="sourceCode cpp">std2<span class="op">::</span>initializer_list</code>
is more a vector, in that it destroys un-consumed objects when dropped,
but also like a view, in that sees into another object’s storage.</p>
<div class="sourceCode" id="cb42"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb42-1"><a href="#cb42-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">+&gt;</span></span>
<span id="cb42-2"><a href="#cb42-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> initializer_list<span class="op">/(</span>a<span class="op">)</span> <span class="op">{</span></span>
<span id="cb42-3"><a href="#cb42-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Point to byte data on the stack.</span></span>
<span id="cb42-4"><a href="#cb42-4" aria-hidden="true" tabindex="-1"></a>  T<span class="op">*</span> unsafe _cur;</span>
<span id="cb42-5"><a href="#cb42-5" aria-hidden="true" tabindex="-1"></a>  T<span class="op">*</span> _end;</span>
<span id="cb42-6"><a href="#cb42-6" aria-hidden="true" tabindex="-1"></a>  T<span class="op">^/</span>a __phantom_data;</span>
<span id="cb42-7"><a href="#cb42-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-8"><a href="#cb42-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">explicit</span></span>
<span id="cb42-9"><a href="#cb42-9" aria-hidden="true" tabindex="-1"></a>  initializer_list<span class="op">([</span>T; dyn<span class="op">]^/</span>a data<span class="op">)</span> <span class="kw">noexcept</span> safe <span class="op">:</span></span>
<span id="cb42-10"><a href="#cb42-10" aria-hidden="true" tabindex="-1"></a>    _cur<span class="op">((*</span>data<span class="op">)~</span>as_pointer<span class="op">)</span>,</span>
<span id="cb42-11"><a href="#cb42-11" aria-hidden="true" tabindex="-1"></a>    unsafe _end<span class="op">((*</span>data<span class="op">)~</span>as_pointer <span class="op">+</span> <span class="op">(*</span>data<span class="op">)~</span>length<span class="op">)</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb42-12"><a href="#cb42-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-13"><a href="#cb42-13" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb42-14"><a href="#cb42-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-15"><a href="#cb42-15" aria-hidden="true" tabindex="-1"></a>  <span class="op">~</span>initializer_list<span class="op">()</span> safe <span class="kw">requires</span><span class="op">(</span>T<span class="op">~</span>is_trivially_destructible<span class="op">)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb42-16"><a href="#cb42-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-17"><a href="#cb42-17" aria-hidden="true" tabindex="-1"></a>  <span class="op">[[</span><span class="at">unsafe</span><span class="op">::</span><span class="at">drop_only</span><span class="op">(</span><span class="at">T</span><span class="op">)]]</span></span>
<span id="cb42-18"><a href="#cb42-18" aria-hidden="true" tabindex="-1"></a>  <span class="op">~</span>initializer_list<span class="op">()</span> safe <span class="kw">requires</span><span class="op">(!</span>T<span class="op">~</span>is_trivially_destructible<span class="op">)</span> <span class="op">{</span></span>
<span id="cb42-19"><a href="#cb42-19" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>destroy_n<span class="op">(</span>_cur, _end <span class="op">-</span> _cur<span class="op">)</span>;</span>
<span id="cb42-20"><a href="#cb42-20" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb42-21"><a href="#cb42-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-22"><a href="#cb42-22" aria-hidden="true" tabindex="-1"></a>  optional<span class="op">&lt;</span>T<span class="op">&gt;</span> next<span class="op">(</span>self<span class="op">^)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb42-23"><a href="#cb42-23" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span><span class="op">(</span>self<span class="op">-&gt;</span>_cur <span class="op">!=</span> self<span class="op">-&gt;</span>_end<span class="op">)</span></span>
<span id="cb42-24"><a href="#cb42-24" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> <span class="op">.</span>some<span class="op">(</span>__rel_read<span class="op">(</span>self<span class="op">-&gt;</span>_cur<span class="op">++))</span>;</span>
<span id="cb42-25"><a href="#cb42-25" aria-hidden="true" tabindex="-1"></a>    <span class="cf">else</span></span>
<span id="cb42-26"><a href="#cb42-26" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> <span class="op">.</span>none;</span>
<span id="cb42-27"><a href="#cb42-27" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb42-28"><a href="#cb42-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-29"><a href="#cb42-29" aria-hidden="true" tabindex="-1"></a>  T<span class="op">*</span> data<span class="op">(</span>self<span class="op">^)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb42-30"><a href="#cb42-30" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> self<span class="op">-&gt;</span>_cur;</span>
<span id="cb42-31"><a href="#cb42-31" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb42-32"><a href="#cb42-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-33"><a href="#cb42-33" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> T<span class="op">*</span> data<span class="op">(</span><span class="kw">const</span> self<span class="op">^)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb42-34"><a href="#cb42-34" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> self<span class="op">-&gt;</span>_cur;</span>
<span id="cb42-35"><a href="#cb42-35" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb42-36"><a href="#cb42-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-37"><a href="#cb42-37" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span><span class="dt">size_t</span> size<span class="op">(</span><span class="kw">const</span> self<span class="op">^)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb42-38"><a href="#cb42-38" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">(</span>std<span class="op">::</span><span class="dt">size_t</span><span class="op">)(</span>self<span class="op">-&gt;</span>_end <span class="op">-</span> self<span class="op">-&gt;</span>_cur<span class="op">)</span>;</span>
<span id="cb42-39"><a href="#cb42-39" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb42-40"><a href="#cb42-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-41"><a href="#cb42-41" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Unsafe call to advance. Use this after relocating data out of</span></span>
<span id="cb42-42"><a href="#cb42-42" aria-hidden="true" tabindex="-1"></a>  <span class="co">// data().</span></span>
<span id="cb42-43"><a href="#cb42-43" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> advance<span class="op">(</span>self<span class="op">^</span>, std<span class="op">::</span><span class="dt">size_t</span> size<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb42-44"><a href="#cb42-44" aria-hidden="true" tabindex="-1"></a>    self<span class="op">-&gt;</span>_cur <span class="op">+=</span> <span class="kw">static_cast</span><span class="op">&lt;</span>std<span class="op">::</span><span class="dt">ptrdiff_t</span><span class="op">&gt;(</span>size<span class="op">)</span>;</span>
<span id="cb42-45"><a href="#cb42-45" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb42-46"><a href="#cb42-46" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-47"><a href="#cb42-47" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span>
<span id="cb42-48"><a href="#cb42-48" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p><code class="sourceCode cpp">std2<span class="op">::</span>initializer_list</code>
has a named lifetime parameter,
<code class="sourceCode cpp"><span class="op">/</span>a</code>, which
puts a constraint on the backing store. The private explicit constructor
is called when lowering the braced initializer expression–that’s
compiler magic. The argument to the constructor is a <a href="#tuples-arrays-and-slice">slice</a> borrow to the backing store.
Note the lifetime argument on the borrow is the class’s named lifetime
parameter. This means the backing store outlives the initializer
list.</p>
<p>This class has a relatively rich interface. Of course you can query
for the pointer to the data and its length. But users may also call
<code class="sourceCode cpp">next</code> to pop off an element at a time
and use it much like an <a href="#iterator-invalidation">iterator</a>.
But for element types that are trivially relocatable, users can call
<code class="sourceCode cpp">data</code> and
<code class="sourceCode cpp">size</code> to relocate them in bulk, and
then <code class="sourceCode cpp">advance</code> by the number of
consumed elements. When the
<code class="sourceCode cpp">initializer_list</code> goes out of scope,
it destructs all unconsumed elements.</p>
<h3 data-number="2.2.4" id="scope-and-liveness"><span class="header-section-number">2.2.4</span> Scope and liveness<a href="#scope-and-liveness" class="self-link"></a></h3>
<p>Key to one’s understanding of lifetime safety is the distinction
between scope and liveness. Consider lowering your function to MIR
instructions which are indexed by program points. The set of points at
which an object is initialized is its <em>scope</em>. In normal C++,
this corresponds to its lexical scope. In Safe C++, due to
relocation/destructive move, there are points in the lexical scope where
the object may not be initialized, making the scope a subset of the
lexical scope.</p>
<p>The compiler lowers AST to MIR and runs <em>initialization
analysis</em>, a form of forward dataflow analysis that computes the
scope of all local variables. If a local variable has been relocated or
dropped, and is then named in an expression, the scope information helps
the compiler flag this as an illegal usage.</p>
<p>Liveness is a different property than scope, but they’re often
confused: end users speak of lifetime to mean initialization or scope,
while backend engineers speak of lifetime to mean liveness. Borrow
checking is concerned with liveness. That’s the set of points where the
value stored in a variable (i.e. a specific bit pattern) is subsequently
used.</p>
<div class="sourceCode" id="cb43"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb43-1"><a href="#cb43-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb43-2"><a href="#cb43-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb43-3"><a href="#cb43-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb43-4"><a href="#cb43-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> x <span class="op">=</span> <span class="dv">1</span>;  <span class="co">// x is live due to use of 1 below.</span></span>
<span id="cb43-5"><a href="#cb43-5" aria-hidden="true" tabindex="-1"></a>  f<span class="op">(</span>x<span class="op">)</span>;       <span class="co">// not live, because 1 isn&#39;t loaded out again.</span></span>
<span id="cb43-6"><a href="#cb43-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb43-7"><a href="#cb43-7" aria-hidden="true" tabindex="-1"></a>  x <span class="op">=</span> <span class="dv">2</span>;      <span class="co">// not live, because 2 isn&#39;t loaded out.</span></span>
<span id="cb43-8"><a href="#cb43-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb43-9"><a href="#cb43-9" aria-hidden="true" tabindex="-1"></a>  x <span class="op">=</span> <span class="dv">3</span>;      <span class="co">// live because 3 is used below.</span></span>
<span id="cb43-10"><a href="#cb43-10" aria-hidden="true" tabindex="-1"></a>  f<span class="op">(</span>x<span class="op">)</span>;       <span class="co">// still live, because 3 is used below.</span></span>
<span id="cb43-11"><a href="#cb43-11" aria-hidden="true" tabindex="-1"></a>  f<span class="op">(</span>x<span class="op">)</span>;       <span class="co">// not live, because 3 isn&#39;t used again.</span></span>
<span id="cb43-12"><a href="#cb43-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Live analysis is a reverse dataflow computation. Start at the return
instruction of the control flow graph and work your way up to the entry
point. When you encounter a load instruction, that variable becomes
live. When you encounter a store instruction, that variable is marked
dead.</p>
<p>The liveness property is useful in register alloction: you only care
about representing a variable in register while it’s holding a value
that has an upcoming use. But we’re solving lifetime safety, we’re not
doing code generation. Here, we’re only concerned with liveness as a
property of <em>borrows</em>.</p>
<div class="sourceCode" id="cb44"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb44-1"><a href="#cb44-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb44-2"><a href="#cb44-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb44-3"><a href="#cb44-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-4"><a href="#cb44-4" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb44-5"><a href="#cb44-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span><span class="op">^</span> ref;   <span class="co">// An uninitialized borrow.</span></span>
<span id="cb44-6"><a href="#cb44-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb44-7"><a href="#cb44-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> x <span class="op">=</span> <span class="dv">1</span>;</span>
<span id="cb44-8"><a href="#cb44-8" aria-hidden="true" tabindex="-1"></a>    ref <span class="op">=</span> <span class="op">^</span>x; <span class="co">// *ref is dereferenced below, so ref is live.</span></span>
<span id="cb44-9"><a href="#cb44-9" aria-hidden="true" tabindex="-1"></a>    f<span class="op">(*</span>ref<span class="op">)</span>;  <span class="co">// now ref is dead.</span></span>
<span id="cb44-10"><a href="#cb44-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-11"><a href="#cb44-11" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> y <span class="op">=</span> <span class="dv">2</span>;</span>
<span id="cb44-12"><a href="#cb44-12" aria-hidden="true" tabindex="-1"></a>    ref <span class="op">=</span> <span class="op">^</span>y; <span class="co">// ref is live again</span></span>
<span id="cb44-13"><a href="#cb44-13" aria-hidden="true" tabindex="-1"></a>    f<span class="op">(*</span>ref<span class="op">)</span>;  <span class="co">// ref is still live, due to read below.</span></span>
<span id="cb44-14"><a href="#cb44-14" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb44-15"><a href="#cb44-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-16"><a href="#cb44-16" aria-hidden="true" tabindex="-1"></a>  f<span class="op">(*</span>ref<span class="op">)</span>;    <span class="co">// ref is live but y is uninitialized.</span></span>
<span id="cb44-17"><a href="#cb44-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Borrows are checked references. It’s a compile-time error to use a
borrow after the data it refers to has gone out of scope. Consider the
set of all live references at each point in the program. Is there an
invalidating action on a place referred to by one of these live
references? If so, that’s a contradiction that makes the program
ill-formed. In this example, the contradiction occurs when
<code class="sourceCode cpp">y</code> goes out of scope, because at that
point, <code class="sourceCode cpp">ref</code> is a live reference to
it. What makes <code class="sourceCode cpp">ref</code> live at that
point?–Its use in the last <code class="sourceCode cpp">f<span class="op">(*</span>ref<span class="op">)</span></code>
expression in the program.</p>
<p>It’s not enough to compute liveness of references. To determine the
invalidating actions, it’s important to know which place the live borrow
refers to. <code class="sourceCode cpp">ref</code> is live until the end
of the function, but <code class="sourceCode cpp">x</code> going out of
scope is not an invalidating function because
<code class="sourceCode cpp">ref</code> doesn’t refer to
<code class="sourceCode cpp">x</code> anymore. We need data structures
that indicate not just when a borrow is live, but to which places it may
refer.</p>
<h3 data-number="2.2.5" id="systems-of-constraints"><span class="header-section-number">2.2.5</span> Systems of constraints<a href="#systems-of-constraints" class="self-link"></a></h3>
<p>NLL borrow checking<span class="citation" data-cites="borrow-checking">[<a href="https://rust-lang.github.io/rfcs/2094-nll.html" role="doc-biblioref">borrow-checking</a>]</span> tests invalidating
actions against live borrows in the presence of control flow. The
algorithm involves generating a system of lifetime constraints which
relate regions at program points, growing region variables until all the
constraints are satisfied, and then testing invalidating actions against
all loans in scope.</p>
<p>A loan is the action that forms a borrow to a place. In the example
above, there are two loans:
<code class="sourceCode cpp"><span class="op">^</span>x</code> and
<code class="sourceCode cpp"><span class="op">^</span>y</code>. Solving
the constraint equation extends the liveness of loans
<code class="sourceCode cpp"><span class="op">^</span>x</code> and
<code class="sourceCode cpp"><span class="op">^</span>y</code> up until
their last indirect uses through
<code class="sourceCode cpp">ref</code>. When
<code class="sourceCode cpp">y</code> goes out of scope, it doesn’t
invalidate the loan
<code class="sourceCode cpp"><span class="op">^</span>x</code>, because
that’s not live. But it does invalidate the loan
<code class="sourceCode cpp"><span class="op">^</span>y</code>, which is
lifetime extended by the final <code class="sourceCode cpp">f<span class="op">(*</span>ref<span class="op">)</span></code>
expression.</p>
<p>Liveness is stored in bit vectors called <em>regions variables</em>.
There are region variables for loans
<code class="sourceCode cpp"><span class="op">^</span>x</code> and
<code class="sourceCode cpp"><span class="op">^</span>y</code> and
regions for objects with borrow types, such as
<code class="sourceCode cpp">ref</code>. There are also regions for
user-defined types with lifetime parameters, such as
<code class="sourceCode cpp">string_view</code>.</p>
<p>A lifetime constraint <code class="sourceCode cpp"><span class="ch">&#39;R</span><span class="er">0 : </span><span class="ch">&#39;</span>R1 <span class="op">:</span> P</code>
reads “region 0 outlives region 1 at point P.” The compiler emits
constraints when encountering assignment and function calls involving
types with regions.</p>
<div class="sourceCode" id="cb45"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb45-1"><a href="#cb45-1" aria-hidden="true" tabindex="-1"></a>    <span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb45-2"><a href="#cb45-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> f<span class="op">(</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb45-3"><a href="#cb45-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb45-4"><a href="#cb45-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb45-5"><a href="#cb45-5" aria-hidden="true" tabindex="-1"></a>P0<span class="op">:</span>   <span class="dt">int</span><span class="op">^</span> ref;          <span class="co">// ref is &#39;R0</span></span>
<span id="cb45-6"><a href="#cb45-6" aria-hidden="true" tabindex="-1"></a>      <span class="op">{</span></span>
<span id="cb45-7"><a href="#cb45-7" aria-hidden="true" tabindex="-1"></a>P1<span class="op">:</span>     <span class="dt">int</span> x <span class="op">=</span> <span class="dv">1</span>;</span>
<span id="cb45-8"><a href="#cb45-8" aria-hidden="true" tabindex="-1"></a>P2<span class="op">:</span>     <span class="op">&lt;</span>loan R1<span class="op">&gt;</span> <span class="op">=</span> <span class="op">^</span>x;  <span class="co">// ^x is loan &#39;R1</span></span>
<span id="cb45-9"><a href="#cb45-9" aria-hidden="true" tabindex="-1"></a>P3<span class="op">:</span>     ref <span class="op">=</span> <span class="op">&lt;</span>loan R1<span class="op">&gt;</span>; <span class="co">// &#39;R1 : &#39;R0 @ P3</span></span>
<span id="cb45-10"><a href="#cb45-10" aria-hidden="true" tabindex="-1"></a>P4<span class="op">:</span>     f<span class="op">(*</span>ref<span class="op">)</span>;</span>
<span id="cb45-11"><a href="#cb45-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb45-12"><a href="#cb45-12" aria-hidden="true" tabindex="-1"></a>P5<span class="op">:</span>     <span class="dt">int</span> y <span class="op">=</span> <span class="dv">2</span>;</span>
<span id="cb45-13"><a href="#cb45-13" aria-hidden="true" tabindex="-1"></a>P6<span class="op">:</span>     <span class="op">&lt;</span>loan R2<span class="op">&gt;</span> <span class="op">=</span> <span class="op">^</span>y;  <span class="co">// ^y is loan &#39;R2</span></span>
<span id="cb45-14"><a href="#cb45-14" aria-hidden="true" tabindex="-1"></a>P7<span class="op">:</span>     ref <span class="op">=</span> <span class="op">&lt;</span>loan R2<span class="op">&gt;</span>; <span class="co">// &#39;R2 : &#39;R0 @ P7</span></span>
<span id="cb45-15"><a href="#cb45-15" aria-hidden="true" tabindex="-1"></a>P8<span class="op">:</span>     f<span class="op">(*</span>ref<span class="op">)</span>;</span>
<span id="cb45-16"><a href="#cb45-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb45-17"><a href="#cb45-17" aria-hidden="true" tabindex="-1"></a>P9<span class="op">:</span>     drop y</span>
<span id="cb45-18"><a href="#cb45-18" aria-hidden="true" tabindex="-1"></a>P10<span class="op">:</span>    drop x</span>
<span id="cb45-19"><a href="#cb45-19" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb45-20"><a href="#cb45-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb45-21"><a href="#cb45-21" aria-hidden="true" tabindex="-1"></a>P11<span class="op">:</span>  f<span class="op">(*</span>ref<span class="op">)</span>;</span>
<span id="cb45-22"><a href="#cb45-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span></code></pre></div>
<p>I’ve relabelled the example to show function points and region names
of variables and loans. If we run live analysis on ’R0, the region for
the variable <code class="sourceCode cpp">ref</code>, we see it’s live
at points ’R0 = { 4, 8, 9, 10, 11 }. These are the points where its
subsequently used. We’ll grow the loan regions ’R1 and ’R2 until their
constraint equations are satisfied.</p>
<p><code class="sourceCode cpp"><span class="ch">&#39;R</span><span class="er">1 : </span><span class="ch">&#39;</span>R0 <span class="op">@</span> P3</code>
means that starting at P3, the ’R1 contains all points ’R0 does, along
all control flow paths, as long as ’R0 is live. ’R1 = { 3, 4 }. Grow ’R2
the same way: ’R2 = { 7, 8, 9, 10, 11 }.</p>
<p>Now we can hunt for contradictions. Visit each point in the function
and consider, “is there a read, write, move, drop or other invalidating
action on any of the loans in scope?” The only potential invalidating
actions are the drops of <code class="sourceCode cpp">x</code> and
<code class="sourceCode cpp">y</code> where they go out of scope. At P9,
the loan <code class="sourceCode cpp"><span class="op">^</span>y</code>
is in scope, because P9 is an element of its region ’R2. This is a
conflicting action, because the loan is also on the variable
<code class="sourceCode cpp">y</code>. That raises a borrow checker
error. There’s also a drop at P10. P10 is in the region for
<code class="sourceCode cpp"><span class="op">^</span>y</code>, but that
is not an invalidating action, because the loan is not on a place that
overlaps with with <code class="sourceCode cpp">x</code>, the operand of
the drop.</p>
<p>The law of exclusivity is enforced at this point. A new mutable loan
is an invalidating action on loans that are live at an overlapping
place. A new shared loan is an invalidating action on mutable loans that
are live at an overlapping place. Additionally, storing to variables is
always an invalidating action when there is any loan, shared or mutable,
on an overlapping place.</p>
<h3 data-number="2.2.6" id="lifetime-error-reporting"><span class="header-section-number">2.2.6</span> Lifetime error reporting<a href="#lifetime-error-reporting" class="self-link"></a></h3>
<p>The borrow checker is concerned with invalidating actions on in-scope
loans. There are three instructions at play:</p>
<ul>
<li><strong>(B)</strong> The creation of the loan. This is the
lvalue-to-borrow operation, equivalent to an addressof (&amp;).</li>
<li><strong>(A)</strong> The action that invalidates the loan. That
includes taking a mutable borrow on a place with a shared loan, or
taking any borrow or writing to a place with a mutable borrow. These
actions could lead to use-after-free bugs.</li>
<li><strong>(U)</strong> A use that extends the liveness of the borrow
past the point of the invalidating action.</li>
</ul>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/view.cxx"><strong>view.cxx</strong></a>
– <a href="https://godbolt.org/z/qqq3889M4">(Compiler Explorer)</a></p>
<div class="sourceCode" id="cb46"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb46-1"><a href="#cb46-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb46-2"><a href="#cb46-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;std2.h&gt;</span></span>
<span id="cb46-3"><a href="#cb46-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-4"><a href="#cb46-4" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb46-5"><a href="#cb46-5" aria-hidden="true" tabindex="-1"></a>  std2<span class="op">::</span>string s<span class="op">(</span><span class="st">&quot;Hello safety&quot;</span><span class="op">)</span>;</span>
<span id="cb46-6"><a href="#cb46-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-7"><a href="#cb46-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// (B) - borrow occurs here.</span></span>
<span id="cb46-8"><a href="#cb46-8" aria-hidden="true" tabindex="-1"></a>  std2<span class="op">::</span>string_view view <span class="op">=</span> s;</span>
<span id="cb46-9"><a href="#cb46-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-10"><a href="#cb46-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">// (A) - invalidating action</span></span>
<span id="cb46-11"><a href="#cb46-11" aria-hidden="true" tabindex="-1"></a>  s <span class="op">=</span> std2<span class="op">::</span>string<span class="op">(</span><span class="st">&quot;A different string&quot;</span><span class="op">)</span>;</span>
<span id="cb46-12"><a href="#cb46-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-13"><a href="#cb46-13" aria-hidden="true" tabindex="-1"></a>  <span class="co">// (U) - use that extends borrow</span></span>
<span id="cb46-14"><a href="#cb46-14" aria-hidden="true" tabindex="-1"></a>  std2<span class="op">::</span>println<span class="op">(</span>view<span class="op">)</span>;</span>
<span id="cb46-15"><a href="#cb46-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb7"><pre class="sourceCode txt"><code class="sourceCode default"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>$ circle view.cxx</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>safety: during safety checking of int main() safe</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>  borrow checking: view.cxx:14:11</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>    println(view);</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>            ^</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>  use of view depends on expired loan</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>  drop of s between its shared borrow and its use</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>  invalidating operation at view.cxx:11:5</span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>    s = &quot;A different string&quot;;</span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>      ^</span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>  loan created at view.cxx:8:28</span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>    std2::string_view view = s;</span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a>                             ^</span></code></pre></div>
<p>Circle tries to identify all three of these points when forming
borrow checker errors. Usually they’re printed in bottom-to-top order.
That is, the first source location printed is the location of the use of
the invalidated loan. Next, the invalidating action is categorized and
located. Lastly, the creation of the loan is indicated.</p>
<p>The invariants that are tested are established with a network of
lifetime constraints. It might not be the case that the invalidating
action is obviously related to either the place of the loan or the use
that extends the loan. More completely describing the chain of
constraints could help users diagnose borrow checker errors. But there’s
a fine line between presenting an error like the one above, which is
already pretty wordy, and overwhelming programmers with information.</p>
<h3 data-number="2.2.7" id="lifetime-constraints-on-called-functinos"><span class="header-section-number">2.2.7</span> Lifetime constraints on
called functinos<a href="#lifetime-constraints-on-called-functinos" class="self-link"></a></h3>
<p>Borrow checking is easiest to understand when applied to a single
function. The function is lowered to a control flow graph, the compiler
assigns regions to loans and borrow variables, emits lifetime
constraints where there are assignments, iteratively grows regions until
the constraints are solved, and walks the instructions, checking for
invalidating actions on loans in scope. Within the definition of the
function, there’s nothing it can’t analyze. The complexity arises when
passing and receiving borrows through function calls.</p>
<p>Whole program analysis is not practical. In order to extend lifetime
safety guarantees outside of single functions, we have to introduce
<em>lifetime contracts</em> on function boundaries that are satisfied by
both caller and callee. These contracts are noted by <em>lifetime
parameters</em>.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/get.cxx"><strong>get.cxx</strong></a>
– <a href="https://godbolt.org/z/GWrfY5qMT">(Compiler Explorer)</a></p>
<div class="sourceCode" id="cb47"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb47-1"><a href="#cb47-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb47-2"><a href="#cb47-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb47-3"><a href="#cb47-3" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> get_x<span class="op">/(</span>a, b<span class="op">)(</span><span class="kw">const</span> <span class="dt">int</span><span class="op">^/</span>a x, <span class="kw">const</span> <span class="dt">int</span><span class="op">^/</span>b y<span class="op">)</span> <span class="op">-&gt;</span> <span class="kw">const</span> <span class="dt">int</span><span class="op">^/</span>a <span class="op">{</span></span>
<span id="cb47-4"><a href="#cb47-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> x;</span>
<span id="cb47-5"><a href="#cb47-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb47-6"><a href="#cb47-6" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> get_y<span class="op">/(</span>a, b<span class="op">)(</span><span class="kw">const</span> <span class="dt">int</span><span class="op">^/</span>a x, <span class="kw">const</span> <span class="dt">int</span><span class="op">^/</span>b y<span class="op">)</span> <span class="op">-&gt;</span> <span class="kw">const</span> <span class="dt">int</span><span class="op">^/</span>b <span class="op">{</span></span>
<span id="cb47-7"><a href="#cb47-7" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> y;</span>
<span id="cb47-8"><a href="#cb47-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb47-9"><a href="#cb47-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb47-10"><a href="#cb47-10" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb47-11"><a href="#cb47-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> <span class="dt">int</span><span class="op">^</span> ref1;</span>
<span id="cb47-12"><a href="#cb47-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> <span class="dt">int</span><span class="op">^</span> ref2;</span>
<span id="cb47-13"><a href="#cb47-13" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> x <span class="op">=</span> <span class="dv">1</span>;</span>
<span id="cb47-14"><a href="#cb47-14" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb47-15"><a href="#cb47-15" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> y <span class="op">=</span> <span class="dv">2</span>;</span>
<span id="cb47-16"><a href="#cb47-16" aria-hidden="true" tabindex="-1"></a>    ref1 <span class="op">=</span> get_x<span class="op">(</span>x, y<span class="op">)</span>;</span>
<span id="cb47-17"><a href="#cb47-17" aria-hidden="true" tabindex="-1"></a>    ref2 <span class="op">=</span> get_y<span class="op">(</span>x, y<span class="op">)</span>;</span>
<span id="cb47-18"><a href="#cb47-18" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb47-19"><a href="#cb47-19" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> val1 <span class="op">=</span> <span class="op">*</span>ref1;  <span class="co">// OK.</span></span>
<span id="cb47-20"><a href="#cb47-20" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> val2 <span class="op">=</span> <span class="op">*</span>ref2;  <span class="co">// Borrow checker error.</span></span>
<span id="cb47-21"><a href="#cb47-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb48"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb48-1"><a href="#cb48-1" aria-hidden="true" tabindex="-1"></a>$ circle get.cxx</span>
<span id="cb48-2"><a href="#cb48-2" aria-hidden="true" tabindex="-1"></a>safety: get.cxx:20:14</span>
<span id="cb48-3"><a href="#cb48-3" aria-hidden="true" tabindex="-1"></a>  int val2 = *ref2;</span>
<span id="cb48-4"><a href="#cb48-4" aria-hidden="true" tabindex="-1"></a>             ^</span>
<span id="cb48-5"><a href="#cb48-5" aria-hidden="true" tabindex="-1"></a>use of *ref2 depends on expired loan</span>
<span id="cb48-6"><a href="#cb48-6" aria-hidden="true" tabindex="-1"></a>drop of y between its shared borrow and its use</span>
<span id="cb48-7"><a href="#cb48-7" aria-hidden="true" tabindex="-1"></a>y declared at get.cxx:15:9</span>
<span id="cb48-8"><a href="#cb48-8" aria-hidden="true" tabindex="-1"></a>    int y = 2;</span>
<span id="cb48-9"><a href="#cb48-9" aria-hidden="true" tabindex="-1"></a>        ^</span>
<span id="cb48-10"><a href="#cb48-10" aria-hidden="true" tabindex="-1"></a>loan created at get.cxx:17:21</span>
<span id="cb48-11"><a href="#cb48-11" aria-hidden="true" tabindex="-1"></a>    ref2 = get_y(x, y);</span>
<span id="cb48-12"><a href="#cb48-12" aria-hidden="true" tabindex="-1"></a>                    ^</span></code></pre></div>
<p><code class="sourceCode cpp">get_x</code> takes two shared borrow
parameters and returns a shared borrow. The return type is marked with
the lifetime parameter
<code class="sourceCode cpp"><span class="op">/</span>a</code>, which
corresponds with the lifetime argument on the returned value
<code class="sourceCode cpp">x</code>.
<code class="sourceCode cpp">get_y</code> is declared to return a shared
borrow with a lifetime associated with the parameter
<code class="sourceCode cpp">y</code>. Since we’re not specifying an
<em>outlives-constraint</em> between the lifetime parameters, the
function bodies can’t assume anything about how these lifetimes relate
to each other. It would be ill-formed for
<code class="sourceCode cpp">get_x</code> to return
<code class="sourceCode cpp">y</code> or
<code class="sourceCode cpp">get_y</code> to return
<code class="sourceCode cpp">x</code>.</p>
<p>This code raises a borrow checker error when dereferencing
<code class="sourceCode cpp"><span class="op">*</span>ref2</code>. As a
human with access to the definiton of
<code class="sourceCode cpp">get_y</code>, it’s obvious that the use of
<code class="sourceCode cpp">ref2</code> is a use-after-free defect. We
can see that <code class="sourceCode cpp">get_y</code> returns
<code class="sourceCode cpp">y</code>, and
<code class="sourceCode cpp">y</code> goes out of scope by the time
<code class="sourceCode cpp">ref2</code> is used. But static analysis
can’t see this–when <code class="sourceCode cpp">main</code> is being
analyzed, it doesn’t look into the definitions of other functions.
Instead, it’s the lifetime parameterization on the
<code class="sourceCode cpp">get_y</code> declaration which informs the
borrow checker. The call generates a constraint: at the point of the
call, the lifetime on the borrow of the second function parameter
outlives the lifetime on the borrow of the result object. That means
that the region on the loan
<code class="sourceCode cpp"><span class="op">^</span>y</code> in the
<code class="sourceCode cpp">get_y</code> call <em>outlives</em> the
region on the result object <code class="sourceCode cpp">ref2</code> at
point of the call. As long as <code class="sourceCode cpp">ref2</code>
is live, so is the loan on <code class="sourceCode cpp">y</code>. That’s
the transitive property and the result of solving the constraint
equation. When <code class="sourceCode cpp">y</code> goes out of scope,
the borrow checker raises an error, because a loan on it is still in
scope.</p>
<div class="sourceCode" id="cb49"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb49-1"><a href="#cb49-1" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb49-2"><a href="#cb49-2" aria-hidden="true" tabindex="-1"></a>P0<span class="op">:</span>   <span class="kw">const</span> <span class="dt">int</span><span class="op">^</span> ref1;        <span class="co">// ref1 is &#39;R0</span></span>
<span id="cb49-3"><a href="#cb49-3" aria-hidden="true" tabindex="-1"></a>P1<span class="op">:</span>   <span class="kw">const</span> <span class="dt">int</span><span class="op">^</span> ref2;        <span class="co">// ref2 is &#39;R1</span></span>
<span id="cb49-4"><a href="#cb49-4" aria-hidden="true" tabindex="-1"></a>P2<span class="op">:</span>   <span class="dt">int</span> x <span class="op">=</span> <span class="dv">1</span>;</span>
<span id="cb49-5"><a href="#cb49-5" aria-hidden="true" tabindex="-1"></a>      <span class="op">{</span></span>
<span id="cb49-6"><a href="#cb49-6" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> y <span class="op">=</span> <span class="dv">2</span>;</span>
<span id="cb49-7"><a href="#cb49-7" aria-hidden="true" tabindex="-1"></a>P3<span class="op">:</span>     <span class="op">&lt;</span>loan R2<span class="op">&gt;</span> <span class="op">=</span> <span class="op">^</span><span class="kw">const</span> x; <span class="co">// ^const x is &#39;R2</span></span>
<span id="cb49-8"><a href="#cb49-8" aria-hidden="true" tabindex="-1"></a>P4<span class="op">:</span>     <span class="op">&lt;</span>loan R3<span class="op">&gt;</span> <span class="op">=</span> <span class="op">^</span><span class="kw">const</span> y; <span class="co">// ^const y is &#39;R3</span></span>
<span id="cb49-9"><a href="#cb49-9" aria-hidden="true" tabindex="-1"></a>P5<span class="op">:</span>     ref1 <span class="op">=</span> get_x<span class="op">(&lt;</span>loan R2<span class="op">&gt;</span>, <span class="op">&lt;</span>loan R3<span class="op">&gt;)</span>;</span>
<span id="cb49-10"><a href="#cb49-10" aria-hidden="true" tabindex="-1"></a>        <span class="co">// /a is &#39;R4.</span></span>
<span id="cb49-11"><a href="#cb49-11" aria-hidden="true" tabindex="-1"></a>        <span class="co">// /b is &#39;R5.</span></span>
<span id="cb49-12"><a href="#cb49-12" aria-hidden="true" tabindex="-1"></a>        <span class="co">// &#39;R2 : &#39;R4 @ P5</span></span>
<span id="cb49-13"><a href="#cb49-13" aria-hidden="true" tabindex="-1"></a>        <span class="co">// &#39;R3 : &#39;R5 @ P5</span></span>
<span id="cb49-14"><a href="#cb49-14" aria-hidden="true" tabindex="-1"></a>        <span class="co">// &#39;R4 : &#39;R0 @ P5</span></span>
<span id="cb49-15"><a href="#cb49-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb49-16"><a href="#cb49-16" aria-hidden="true" tabindex="-1"></a>P6<span class="op">:</span>     <span class="op">&lt;</span>loan R6<span class="op">&gt;</span> <span class="op">=</span> <span class="op">^</span><span class="kw">const</span> x; <span class="co">// ^const x is &#39;R6</span></span>
<span id="cb49-17"><a href="#cb49-17" aria-hidden="true" tabindex="-1"></a>P7<span class="op">:</span>     <span class="op">&lt;</span>loan R7<span class="op">&gt;</span> <span class="op">=</span> <span class="op">^</span><span class="kw">const</span> y; <span class="co">// ^const y is &#39;R7</span></span>
<span id="cb49-18"><a href="#cb49-18" aria-hidden="true" tabindex="-1"></a>P8<span class="op">:</span>     ref2 <span class="op">=</span> get_y<span class="op">(&lt;</span>loan R6<span class="op">&gt;</span>, <span class="op">&lt;</span>loan R7<span class="op">&gt;)</span>;</span>
<span id="cb49-19"><a href="#cb49-19" aria-hidden="true" tabindex="-1"></a>        <span class="co">// /a is &#39;R8&#39;.</span></span>
<span id="cb49-20"><a href="#cb49-20" aria-hidden="true" tabindex="-1"></a>        <span class="co">// /b is &#39;R9&#39;.</span></span>
<span id="cb49-21"><a href="#cb49-21" aria-hidden="true" tabindex="-1"></a>        <span class="co">// &#39;R6 : &#39;R8 @ P8</span></span>
<span id="cb49-22"><a href="#cb49-22" aria-hidden="true" tabindex="-1"></a>        <span class="co">// &#39;R7 : &#39;R9 @ P8</span></span>
<span id="cb49-23"><a href="#cb49-23" aria-hidden="true" tabindex="-1"></a>        <span class="co">// &#39;R9 : &#39;R1 @ P8</span></span>
<span id="cb49-24"><a href="#cb49-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb49-25"><a href="#cb49-25" aria-hidden="true" tabindex="-1"></a>P9<span class="op">:</span>     drp y</span>
<span id="cb49-26"><a href="#cb49-26" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb49-27"><a href="#cb49-27" aria-hidden="true" tabindex="-1"></a>P10<span class="op">:</span>  <span class="dt">int</span> val1 <span class="op">=</span> <span class="op">*</span>ref1;  <span class="co">// OK.</span></span>
<span id="cb49-28"><a href="#cb49-28" aria-hidden="true" tabindex="-1"></a>P11<span class="op">:</span>  <span class="dt">int</span> val2 <span class="op">=</span> <span class="op">*</span>ref2;  <span class="co">// Borrow checker error.</span></span>
<span id="cb49-29"><a href="#cb49-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb49-30"><a href="#cb49-30" aria-hidden="true" tabindex="-1"></a>P12<span class="op">:</span>  drp x</span>
<span id="cb49-31"><a href="#cb49-31" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span></code></pre></div>
<p>For every function call, the lifetime parameters of that function are
assigned regions distinct from the regions of the arguments and result
object. This is done to more cleanly support <a href="#lifetime-parameters"><em>outlives-constraints</em></a>. The
regions of the function arguments outlive their corresponding lifetime
parameters, and the lifetime parameters outlive their corresponding
result object regions. This creates a chain of custody in from the
arguments, through the function’s lifetime parameters, and out through
the result object. The caller doesn’t have to know the definition of the
function, because it upholds the constraints at the point of the call,
and the callee upholds the constraints in the definition of the
function.</p>
<p>Let’s solve for the regions of the four loans:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode txt"><code class="sourceCode default"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>&#39;R2 = { 4, 5, 6, 7, 8, 9, 10 }</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>&#39;R3 = { 5 }</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>&#39;R6 = { 7, 8, }</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>&#39;R7 = { 8, 9, 10, 11 }</span></code></pre></div>
<p>The drops of <code class="sourceCode cpp">x</code> and
<code class="sourceCode cpp">y</code> are the potentially invalidating
actions. <code class="sourceCode cpp">y</code> goes out of scope at P9,
and the loans with regions <code class="sourceCode cpp">R2</code> and
<code class="sourceCode cpp">R7</code> are live at P9 (because they have
9 in their sets). The ’R2 loan borrows variable
<code class="sourceCode cpp">x</code>, which is non-overlapping with the
drop operand <code class="sourceCode cpp">y</code>, so it’s not an
invalidating action. The ’R7 loan borrows variable
<code class="sourceCode cpp">y</code>, which is overlapping with the
drop operand <code class="sourceCode cpp">y</code>, so we get a borrow
checker error. The drop of <code class="sourceCode cpp">x</code> is
benign, since no loan is live at P12.</p>
<h3 data-number="2.2.8" id="lifetime-parameters"><span class="header-section-number">2.2.8</span> Lifetime parameters<a href="#lifetime-parameters" class="self-link"></a></h3>
<p>On function types and function declarators, the
<em>lifetime-parameters-list</em> goes right after the
<em>declarator-id</em>.</p>
<div class="sourceCode" id="cb50"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb50-1"><a href="#cb50-1" aria-hidden="true" tabindex="-1"></a><span class="co">// A function type declarator.</span></span>
<span id="cb50-2"><a href="#cb50-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> F1 <span class="op">=</span> <span class="dt">void</span><span class="op">/(</span>a, b<span class="op">)(</span><span class="dt">int</span><span class="op">^/</span>a, <span class="dt">int</span><span class="op">^/</span>b<span class="op">)</span> safe;</span>
<span id="cb50-3"><a href="#cb50-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb50-4"><a href="#cb50-4" aria-hidden="true" tabindex="-1"></a><span class="co">// A function declaration with the same type</span></span>
<span id="cb50-5"><a href="#cb50-5" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f1<span class="op">/(</span>a, b<span class="op">)(</span><span class="dt">int</span><span class="op">^/</span>a, <span class="dt">int</span><span class="op">^/</span>b<span class="op">)</span> safe;</span></code></pre></div>
<p>Borrows are first-class <em>lifetime binders</em>. You can also
declare class and class templates that bind lifetimes by putting
<em>lifetime-parameters-lists</em> after their
<em>declarator-ids</em>.</p>
<div class="sourceCode" id="cb51"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb51-1"><a href="#cb51-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> char_type<span class="op">&gt;</span></span>
<span id="cb51-2"><a href="#cb51-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> basic_string_view<span class="op">/(</span>a<span class="op">)</span>;</span></code></pre></div>
<p>All types with lifetime binders named in function declarations and
data members must be qualified with lifetime arguments. This helps
define the lifetime contract between callers and callees. Often it’s
necessary to specify requirements between lifetime parameters. These
take the form of <em>outlives-constraints</em>. They’re specified in a
<em>where-clause</em> inside the <em>lifetime-parameter-list</em>:</p>
<div class="sourceCode" id="cb52"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb52-1"><a href="#cb52-1" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> F2 <span class="op">=</span> <span class="dt">void</span><span class="op">/(</span>a, b where a <span class="op">:</span> b<span class="op">)(</span><span class="dt">int</span><span class="op">^/</span>a x, <span class="dt">int</span><span class="op">^/</span>b y<span class="op">)</span> safe;</span></code></pre></div>
<p>Rust chose a different syntax, mixing lifetime parameters and type
parameters into the same parameter list. Coming from C++, where
templates supply our generics, I find this misleading. Lifetime
parameters are nothing like template parameters. A function with
lifetime parameters isn’t really a generic function. Lifetime parameters
are never substituted with any kind of concrete lifetime argument.
Instead, the relationship between lifetime parameters, as deduced from
<em>outlives-constraints</em>, implied bounds and variances of function
parameters, establishes constraints that are used by the borrow checker
at the point of call.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="co">// A Rust declaration.</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> f<span class="op">&lt;</span><span class="ot">&#39;a</span><span class="op">,</span> <span class="ot">&#39;b</span><span class="op">,</span> T<span class="op">&gt;</span>(x<span class="op">:</span> <span class="op">&amp;</span><span class="ot">&#39;a</span> <span class="kw">mut</span> T<span class="op">,</span> y<span class="op">:</span> <span class="op">&amp;</span><span class="ot">&#39;b</span> T) <span class="kw">where</span> <span class="ot">&#39;a</span> <span class="op">:</span> <span class="ot">&#39;b</span> <span class="op">{</span> <span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb53"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb53-1"><a href="#cb53-1" aria-hidden="true" tabindex="-1"></a><span class="co">// A C++ declaration.</span></span>
<span id="cb53-2"><a href="#cb53-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb53-3"><a href="#cb53-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">/(</span>a, b where a <span class="op">:</span> b<span class="op">)(</span>T<span class="op">^/</span>a x, <span class="kw">const</span> T<span class="op">^/</span>b y<span class="op">)</span> <span class="op">{</span> <span class="op">}</span></span></code></pre></div>
<p>Rust uses single-quotes to introduce lifetime parameters and lifetime
arguments. That’s not a workable choice for us, because C supports
multi-character literals. This cursed feature, in which literals like
<code class="sourceCode cpp"><span class="ch">&#39;a</span><span class="er">bcd</span><span class="ch">&#39;</span></code>
evaluate to constants of type
<code class="sourceCode cpp"><span class="dt">int</span></code>, makes
lexing Rust-style lifetime arguments very messy.</p>
<div class="sourceCode" id="cb54"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb54-1"><a href="#cb54-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb54-2"><a href="#cb54-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">/(</span>a, b where a <span class="op">:</span> b<span class="op">)(</span>T<span class="op">^/</span>a x, <span class="kw">const</span> T<span class="op">^/</span>b y<span class="op">)</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb54-3"><a href="#cb54-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb54-4"><a href="#cb54-4" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb54-5"><a href="#cb54-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> x <span class="op">=</span> <span class="dv">1</span>;</span>
<span id="cb54-6"><a href="#cb54-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> y <span class="op">=</span> <span class="dv">2</span>;</span>
<span id="cb54-7"><a href="#cb54-7" aria-hidden="true" tabindex="-1"></a>  f<span class="op">(^</span>x, y<span class="op">)</span>;</span>
<span id="cb54-8"><a href="#cb54-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb55"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb55-1"><a href="#cb55-1" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb55-2"><a href="#cb55-2" aria-hidden="true" tabindex="-1"></a>P0<span class="op">:</span>   <span class="dt">int</span> x <span class="op">=</span> <span class="dv">1</span>;</span>
<span id="cb55-3"><a href="#cb55-3" aria-hidden="true" tabindex="-1"></a>P1<span class="op">:</span>   <span class="dt">int</span> y <span class="op">=</span> <span class="dv">2</span>;</span>
<span id="cb55-4"><a href="#cb55-4" aria-hidden="true" tabindex="-1"></a>P2<span class="op">:</span>   <span class="op">&lt;</span>loan R0<span class="op">&gt;</span> <span class="op">=</span> <span class="op">^</span>x;</span>
<span id="cb55-5"><a href="#cb55-5" aria-hidden="true" tabindex="-1"></a>P3<span class="op">:</span>   <span class="op">&lt;</span>loan R1<span class="op">&gt;</span> <span class="op">=</span> <span class="op">^</span><span class="kw">const</span> y;</span>
<span id="cb55-6"><a href="#cb55-6" aria-hidden="true" tabindex="-1"></a>P4<span class="op">:</span>   f<span class="op">(&lt;</span>loan R0<span class="op">&gt;</span>, <span class="op">&lt;</span>loan R1<span class="op">&gt;)</span>;</span>
<span id="cb55-7"><a href="#cb55-7" aria-hidden="true" tabindex="-1"></a>      <span class="co">// /a is &#39;R2</span></span>
<span id="cb55-8"><a href="#cb55-8" aria-hidden="true" tabindex="-1"></a>      <span class="co">// /b is &#39;R3</span></span>
<span id="cb55-9"><a href="#cb55-9" aria-hidden="true" tabindex="-1"></a>      <span class="co">// &#39;R2 : &#39;R3 @ P4 - `where a : b`</span></span>
<span id="cb55-10"><a href="#cb55-10" aria-hidden="true" tabindex="-1"></a>      <span class="co">// &#39;R0 : &#39;R2 @ P4</span></span>
<span id="cb55-11"><a href="#cb55-11" aria-hidden="true" tabindex="-1"></a>      <span class="co">// &#39;R1 : &#39;R3 @ P4</span></span>
<span id="cb55-12"><a href="#cb55-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span></code></pre></div>
<p>The <em>where-clause</em> establishes the relationship that
<code class="sourceCode cpp"><span class="op">/</span>a</code> outlives
<code class="sourceCode cpp"><span class="op">/</span>b</code>. Does
this mean that the variable pointed at by
<code class="sourceCode cpp">x</code> goes out of scope later than the
variable pointed at by <code class="sourceCode cpp">y</code>? No, that
would be too straight-forward. This declaration emits a
<em>lifetime-constraint</em> at the point of the function call. The
regions of the arguments already constrain the regions of the lifetime
parameters. The <em>where-clause</em> constrains the lifetime parameters
to each other. <code class="sourceCode cpp">f</code>’s outlives
constraint is responsible for the lifetime constraint <code class="sourceCode cpp"><span class="ch">&#39;R</span><span class="er">2 : </span><span class="ch">&#39;</span>R3 <span class="op">@</span> P4</code>.</p>
<p>Lifetime parameters and <em>where-clauses</em> are a facility for
instructing the borrow checker. The obvious mental model is that the
lifetimes of references are connected to the scope of the objects they
point to. But this is not accurate. Think about lifetimes as defining
rules that can’t be violated, with the borrow checker looking for
contradictions of these rules.</p>
<h3 data-number="2.2.9" id="destructors-and-phantom-data"><span class="header-section-number">2.2.9</span> Destructors and phantom
data<a href="#destructors-and-phantom-data" class="self-link"></a></h3>
<p>Safe C++ includes an operator to call the destructor on local
objects.</p>
<ul>
<li><code class="sourceCode cpp">drp x</code> - call the destructor on
an object and set as uninitialized.</li>
</ul>
<p>Local objects start off uninitialized. They’re initialized when first
assigned to. Then they’re uninitialized again when relocated from. If
you want to <em>destruct</em> an object prior to it going out of scope,
use <em>drp-expression</em>. Unlike Rust’s
<code class="sourceCode cpp">drop</code> API,<span class="citation" data-cites="drop">[<a href="https://doc.rust-lang.org/std/ops/trait.Drop.html" role="doc-biblioref">drop</a>]</span> this works even on objects that
are pinned or are only potentially initialized (was uninitialized on
some control flow paths) or partially initialized (has some
uninitialized subobjects). This is useful feature for the affine type
system. But it’s presented in the borrow checking section. Why? Because
the operand of a <em>drp-expression</em> isn’t a normal use, in the
borrow checking sense. It’s a special <em>drop use</em>.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/drop.rs"><strong>drop.rs</strong></a>
– <a href="https://godbolt.org/z/hsYdqqxTe">(Compiler Explorer)</a></p>
<div class="sourceCode" id="cb10"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">let</span> <span class="kw">mut</span> v <span class="op">=</span> <span class="dt">Vec</span><span class="pp">::</span><span class="op">&lt;&amp;</span><span class="dt">i32</span><span class="op">&gt;</span><span class="pp">::</span>new()<span class="op">;</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> x <span class="op">=</span> <span class="dv">101</span><span class="op">;</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>    v<span class="op">.</span>push(<span class="op">&amp;</span>x)<span class="op">;</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Error: `x` does not live long enough</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>  drop(v)<span class="op">;</span></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb56"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb56-1"><a href="#cb56-1" aria-hidden="true" tabindex="-1"></a>$ rustc drop.rs</span>
<span id="cb56-2"><a href="#cb56-2" aria-hidden="true" tabindex="-1"></a>error[E0597]: `x` does not live long enough</span>
<span id="cb56-3"><a href="#cb56-3" aria-hidden="true" tabindex="-1"></a> --&gt; drop.rs:5:12</span>
<span id="cb56-4"><a href="#cb56-4" aria-hidden="true" tabindex="-1"></a>  |</span>
<span id="cb56-5"><a href="#cb56-5" aria-hidden="true" tabindex="-1"></a>4 |     let x = 101;</span>
<span id="cb56-6"><a href="#cb56-6" aria-hidden="true" tabindex="-1"></a>  |         - binding `x` declared here</span>
<span id="cb56-7"><a href="#cb56-7" aria-hidden="true" tabindex="-1"></a>5 |     v.push(&amp;x);</span>
<span id="cb56-8"><a href="#cb56-8" aria-hidden="true" tabindex="-1"></a>  |            ^^ borrowed value does not live long enough</span>
<span id="cb56-9"><a href="#cb56-9" aria-hidden="true" tabindex="-1"></a>6 |   }</span>
<span id="cb56-10"><a href="#cb56-10" aria-hidden="true" tabindex="-1"></a>  |   - `x` dropped here while still borrowed</span>
<span id="cb56-11"><a href="#cb56-11" aria-hidden="true" tabindex="-1"></a>...</span>
<span id="cb56-12"><a href="#cb56-12" aria-hidden="true" tabindex="-1"></a>9 |   drop(v);</span>
<span id="cb56-13"><a href="#cb56-13" aria-hidden="true" tabindex="-1"></a>  |        - borrow later used here</span></code></pre></div>
<p>Rust’s <code class="sourceCode cpp">drop</code> API is a normal
function. It performs the usual non-drop-use of all lifetimes on the
operand. A vector with dangling lifetimes would pass the normal drop
check, but when used as an argument to
<code class="sourceCode cpp">drop</code> call, makes the program
ill-formed. The borrow checker in
<code class="sourceCode cpp">main</code> doesn’t know that the body of
the <code class="sourceCode cpp">drop</code> call won’t load or store a
value through that dangling reference.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/drop.cxx"><strong>drop.cxx</strong></a>
– <a href="https://godbolt.org/z/MM14nPdc6">(Compiler Explorer)</a></p>
<div class="sourceCode" id="cb57"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb57-1"><a href="#cb57-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb57-2"><a href="#cb57-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;std2.h&gt;</span></span>
<span id="cb57-3"><a href="#cb57-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb57-4"><a href="#cb57-4" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb57-5"><a href="#cb57-5" aria-hidden="true" tabindex="-1"></a>  std2<span class="op">::</span>vector<span class="op">&lt;</span><span class="kw">const</span> <span class="dt">int</span><span class="op">^&gt;</span> vec <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb57-6"><a href="#cb57-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb57-7"><a href="#cb57-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> x <span class="op">=</span> <span class="dv">101</span>;</span>
<span id="cb57-8"><a href="#cb57-8" aria-hidden="true" tabindex="-1"></a>    mut vec<span class="op">.</span>push_back<span class="op">(</span>x<span class="op">)</span>;</span>
<span id="cb57-9"><a href="#cb57-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb57-10"><a href="#cb57-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb57-11"><a href="#cb57-11" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Okay. vec has dangling borrows, but passes the drop check.</span></span>
<span id="cb57-12"><a href="#cb57-12" aria-hidden="true" tabindex="-1"></a>  drp vec;</span>
<span id="cb57-13"><a href="#cb57-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The <em>drp-expression</em> in Safe C++ isn’t implemented with a
function call. It’s a first-class feature and only performs a <em>drop
use</em> of the operand’s lifetimes. Why is it safe to drop a
<code class="sourceCode cpp">std2<span class="op">::</span>vector</code>
that holds dangling borrows? That’s the result of careful interplay
between <code class="sourceCode cpp">__phantom_data</code> and
<code class="sourceCode cpp">drop_only</code>.</p>
<p>A user-defined destructor uses the lifetimes associated with all
class data members. However, container types that store data in heap
memory, such as box and vector, don’t store their data as data members,
but instead keep pointers into keep memory. In order to expose data for
the drop check, container types must have phantom data<span class="citation" data-cites="phantom-data">[<a href="https://doc.rust-lang.org/nomicon/phantom-data.html" role="doc-biblioref">phantom-data</a>]</span> to declare a sort of
phantom data.</p>
<div class="sourceCode" id="cb58"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb58-1"><a href="#cb58-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">+&gt;</span></span>
<span id="cb58-2"><a href="#cb58-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Vec <span class="op">{</span></span>
<span id="cb58-3"><a href="#cb58-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">~</span>Vec<span class="op">()</span> safe;</span>
<span id="cb58-4"><a href="#cb58-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb58-5"><a href="#cb58-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Pointer to the data. Since T* has a trivial destructor, template</span></span>
<span id="cb58-6"><a href="#cb58-6" aria-hidden="true" tabindex="-1"></a>  <span class="co">// lifetime parameters of T are not used by Vec&#39;s dtor.</span></span>
<span id="cb58-7"><a href="#cb58-7" aria-hidden="true" tabindex="-1"></a>  T<span class="op">*</span> _data;</span>
<span id="cb58-8"><a href="#cb58-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb58-9"><a href="#cb58-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">// For the purpose of drop check, declare a member of type T.</span></span>
<span id="cb58-10"><a href="#cb58-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">// This is a phantom data member that does not effect data</span></span>
<span id="cb58-11"><a href="#cb58-11" aria-hidden="true" tabindex="-1"></a>  <span class="co">// layout or initialization.</span></span>
<span id="cb58-12"><a href="#cb58-12" aria-hidden="true" tabindex="-1"></a>  T __phantom_data;</span>
<span id="cb58-13"><a href="#cb58-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>Including a <code class="sourceCode cpp">__phantom_data</code> member
informs the compiler that the class may use objects of type
<code class="sourceCode cpp">T</code> inside the user-defined
destructor. The drop check expects user-defined destructors to be
maximally permissive with its data members, and that it can use any of
the class’s lifetime parameters. For a <code class="sourceCode cpp">Vec<span class="op">&lt;</span><span class="kw">const</span> <span class="dt">int</span><span class="op">^&gt;</span></code>
type, the destructor could dereference its elements and print out their
values before freeing their storage. The
<code class="sourceCode cpp">__phantom_data</code> declares that a type
will be used like a data member in the user-defined destructor. Without
this annotaton, the destructor could load from a dangling reference and
cause a use-after-free bug.</p>
<p>In order to permit <em>dangling references</em> in containers,
destructors opt into the <code class="sourceCode cpp"><span class="op">[[</span><span class="at">unsafe</span><span class="op">::</span><span class="at">drop_only</span><span class="op">(</span><span class="at">T</span><span class="op">)]]</span></code>
attribute. It’s available in Rust as the <code class="sourceCode cpp"><span class="pp">#</span><span class="er">[may_dangle]</span></code>
attribute.<span class="citation" data-cites="may-dangle">[<a href="https://rust-lang.github.io/rfcs/1327-dropck-param-eyepatch.html" role="doc-biblioref">may-dangle</a>]</span> This attribute is a promise
that the user-defined destructor will only destroy the type in
attribute’s operand. Permitting dangling references in a <em>drop
use</em> is a crucial feature. Without it, objects may squabble over
destruction order, resulting in code that fights the borrow checker.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/drop2.cxx"><strong>drop2.cxx</strong></a>
– <a href="https://godbolt.org/z/qv1nq65oa">(Compiler Explorer)</a></p>
<div class="sourceCode" id="cb59"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb59-1"><a href="#cb59-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb59-2"><a href="#cb59-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb59-3"><a href="#cb59-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">+</span>, <span class="dt">bool</span> DropOnly<span class="op">&gt;</span></span>
<span id="cb59-4"><a href="#cb59-4" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Vec <span class="op">{</span></span>
<span id="cb59-5"><a href="#cb59-5" aria-hidden="true" tabindex="-1"></a>  Vec<span class="op">()</span> safe <span class="op">{</span> <span class="op">}</span></span>
<span id="cb59-6"><a href="#cb59-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb59-7"><a href="#cb59-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">[[</span><span class="at">unsafe</span><span class="op">::</span><span class="at">drop_only</span><span class="op">(</span><span class="at">T</span><span class="op">)]]</span> <span class="op">~</span>Vec<span class="op">()</span> safe <span class="kw">requires</span><span class="op">(</span>DropOnly<span class="op">)</span>;</span>
<span id="cb59-8"><a href="#cb59-8" aria-hidden="true" tabindex="-1"></a>                           <span class="op">~</span>Vec<span class="op">()</span> safe <span class="kw">requires</span><span class="op">(!</span>DropOnly<span class="op">)</span>;</span>
<span id="cb59-9"><a href="#cb59-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb59-10"><a href="#cb59-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> push<span class="op">(</span>self<span class="op">^</span>, T rhs<span class="op">)</span> safe;</span>
<span id="cb59-11"><a href="#cb59-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb59-12"><a href="#cb59-12" aria-hidden="true" tabindex="-1"></a>  <span class="co">// T is a phantom data member of Vec. The non-trivial dtor will</span></span>
<span id="cb59-13"><a href="#cb59-13" aria-hidden="true" tabindex="-1"></a>  <span class="co">// use the lifetimes of T, raising a borrow checker error if</span></span>
<span id="cb59-14"><a href="#cb59-14" aria-hidden="true" tabindex="-1"></a>  <span class="co">// T is not drop_only.</span></span>
<span id="cb59-15"><a href="#cb59-15" aria-hidden="true" tabindex="-1"></a>  T __phantom_data;</span>
<span id="cb59-16"><a href="#cb59-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb59-17"><a href="#cb59-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb59-18"><a href="#cb59-18" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T, <span class="dt">bool</span> DropOnly<span class="op">&gt;</span></span>
<span id="cb59-19"><a href="#cb59-19" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> test<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb59-20"><a href="#cb59-20" aria-hidden="true" tabindex="-1"></a>  Vec<span class="op">&lt;</span><span class="kw">const</span> T<span class="op">^</span>, DropOnly<span class="op">&gt;</span> vec <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb59-21"><a href="#cb59-21" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb59-22"><a href="#cb59-22" aria-hidden="true" tabindex="-1"></a>    T x <span class="op">=</span> <span class="dv">101</span>;</span>
<span id="cb59-23"><a href="#cb59-23" aria-hidden="true" tabindex="-1"></a>    mut vec<span class="op">.</span>push<span class="op">(^</span>x<span class="op">)</span>;</span>
<span id="cb59-24"><a href="#cb59-24" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb59-25"><a href="#cb59-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb59-26"><a href="#cb59-26" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Use of vec is ill-formed due to drop of x above.</span></span>
<span id="cb59-27"><a href="#cb59-27" aria-hidden="true" tabindex="-1"></a>  <span class="co">// int y = 102;</span></span>
<span id="cb59-28"><a href="#cb59-28" aria-hidden="true" tabindex="-1"></a>  <span class="co">// mut vec.push(^y);</span></span>
<span id="cb59-29"><a href="#cb59-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb59-30"><a href="#cb59-30" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Should be ill-formed due to drop check.</span></span>
<span id="cb59-31"><a href="#cb59-31" aria-hidden="true" tabindex="-1"></a>  drp vec;</span>
<span id="cb59-32"><a href="#cb59-32" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb59-33"><a href="#cb59-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb59-34"><a href="#cb59-34" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb59-35"><a href="#cb59-35" aria-hidden="true" tabindex="-1"></a>  test<span class="op">&lt;</span><span class="dt">int</span>, <span class="kw">true</span><span class="op">&gt;()</span>;</span>
<span id="cb59-36"><a href="#cb59-36" aria-hidden="true" tabindex="-1"></a>  test<span class="op">&lt;</span><span class="dt">int</span>, <span class="kw">false</span><span class="op">&gt;()</span>;</span>
<span id="cb59-37"><a href="#cb59-37" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb60"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb60-1"><a href="#cb60-1" aria-hidden="true" tabindex="-1"></a>$ circle drop2.cxx</span>
<span id="cb60-2"><a href="#cb60-2" aria-hidden="true" tabindex="-1"></a>safety: during safety checking of void test&lt;int, false&gt;() safe</span>
<span id="cb60-3"><a href="#cb60-3" aria-hidden="true" tabindex="-1"></a>  borrow checking: drop2.cxx:31:3</span>
<span id="cb60-4"><a href="#cb60-4" aria-hidden="true" tabindex="-1"></a>    drp vec;</span>
<span id="cb60-5"><a href="#cb60-5" aria-hidden="true" tabindex="-1"></a>    ^</span>
<span id="cb60-6"><a href="#cb60-6" aria-hidden="true" tabindex="-1"></a>  use of vec depends on expired loan</span>
<span id="cb60-7"><a href="#cb60-7" aria-hidden="true" tabindex="-1"></a>  drop of x between its mutable borrow and its use</span>
<span id="cb60-8"><a href="#cb60-8" aria-hidden="true" tabindex="-1"></a>  x declared at drop2.cxx:22:7</span>
<span id="cb60-9"><a href="#cb60-9" aria-hidden="true" tabindex="-1"></a>      T x = 101;</span>
<span id="cb60-10"><a href="#cb60-10" aria-hidden="true" tabindex="-1"></a>        ^</span>
<span id="cb60-11"><a href="#cb60-11" aria-hidden="true" tabindex="-1"></a>  loan created at drop2.cxx:23:18</span>
<span id="cb60-12"><a href="#cb60-12" aria-hidden="true" tabindex="-1"></a>      mut vec.push(^x);</span>
<span id="cb60-13"><a href="#cb60-13" aria-hidden="true" tabindex="-1"></a>                   ^</span></code></pre></div>
<p>This example explores the effects of the <code class="sourceCode cpp"><span class="op">[[</span><span class="at">unsafe</span><span class="op">::</span><span class="at">drop_only</span><span class="op">(</span><span class="at">T</span><span class="op">)]]</span></code>
attribute. As of C++ 20, class templates can overload destructors based
on <em>requires-specifier</em>. We want to provide both normal and
<code class="sourceCode cpp">drop_only</code> destructors to test borrow
checking.</p>
<p>A <code class="sourceCode cpp">T __phantom_data</code> member
indicates that <code class="sourceCode cpp">T</code> will be destroyed
as part of the user-defined destructor. The user-defined destructor is
conditionally declared with the <code class="sourceCode cpp"><span class="op">[[</span><span class="at">unsafe</span><span class="op">::</span><span class="at">drop_only</span><span class="op">(</span><span class="at">T</span><span class="op">)]]</span></code>
attribute, which means that the destructor body will only use
<code class="sourceCode cpp">T</code>’s lifetime parameters as part of a
drop, and not any other use.</p>
<p>The point of this mechanism is to make drop order less important by
permitting the drop of containers that hold dangling references. Declare
a <code class="sourceCode cpp">Vec</code> specialized on a <code class="sourceCode cpp"><span class="kw">const</span> <span class="dt">int</span><span class="op">^</span></code>.
Push a shared borrow to a local integer declaration, then make the local
integer go out of scope. The <code class="sourceCode cpp">Vec</code> now
holds a dangling borrow. This should compile, as long as we don’t use
the template lifetime parameter associated with the borrow. That would
produce a use-after-free borrow checker error.</p>
<p>When <code class="sourceCode cpp">DropOnly</code> is true, the
destructor overload with the <code class="sourceCode cpp"><span class="op">[[</span><span class="at">unsafe</span><span class="op">::</span><span class="at">drop_only</span><span class="op">]]</span></code>
attribute is instantiated. The <em>drp-expression</em> in
<code class="sourceCode cpp">test</code> doesn’t automatically use the
lifetimes of its operand. Instead, the drop check considers lifetime
parameters of the operand that are drop used. Due to the <code class="sourceCode cpp"><span class="op">[[</span><span class="at">unsafe</span><span class="op">::</span><span class="at">drop_only</span><span class="op">(</span><span class="at">T</span><span class="op">)]]</span></code>
attribute, the data member is only a <em>drop use</em> rather than a
normal use. And the drop use of a borrow is nothing: it’s a trivial
destructor. We can don’t care about lifetimes of borrows when dropping
them, because we’re doing operations that can cause soundness problems.
The <em>drp-expression</em> destroys the
<code class="sourceCode cpp">Vec</code> without a borrow checker
violation. The programmer is making an unsafe promise not to do anything
with <code class="sourceCode cpp">T</code>’s template lifetime
parameters inside
<code class="sourceCode cpp"><span class="op">~</span>Vec</code> other
than use it to drop <code class="sourceCode cpp">T</code>.</p>
<p>When <code class="sourceCode cpp">DropOnly</code> is false, the
destructor overload without the attribute is instantiated. In this case,
the user-defined destructor is assumed to use all of the class’s
lifetime parameters outside. If the
<code class="sourceCode cpp">Vec</code> held a borrow to out-of-scope
data, as it does in this example, loading that data through the borrow
would be a use-after-free defect. To prevent this unsound behavior, the
compiler uses all the class’s lifetime parameters when its user-defined
destructor is called. This raises the borrow checker error, indicating
that the <em>drp-expression</em> depends on an expired loan on
<code class="sourceCode cpp">x</code>.</p>
<p>The <code class="sourceCode cpp">drop_only</code> attribute is
currently <code class="sourceCode cpp">unsafe</code> because it depends
on the programmer following through with a promising not to do anything
with the operand other than to destruct it. We plan to make this
attribute safe. The compiler should be able to monitor the user-defined
destructor for use of lifetimes associated with
<code class="sourceCode cpp">T</code> outside of drops and raise borrow
checker errors. However, that may require extending
<code class="sourceCode cpp">drop_only</code> to all functions, not just
destructors. <code class="sourceCode cpp">std<span class="op">::</span>destruct_at</code>
involves a non-drop use of the parameter type. But a
<code class="sourceCode cpp">drop_only</code>-attributed <code class="sourceCode cpp">std2<span class="op">::</span>destruct_at</code>
would only permit and qualify as a drop use.</p>
<h3 data-number="2.2.10" id="lifetime-canonicalization"><span class="header-section-number">2.2.10</span> Lifetime canonicalization<a href="#lifetime-canonicalization" class="self-link"></a></h3>
<div class="sourceCode" id="cb61"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb61-1"><a href="#cb61-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb61-2"><a href="#cb61-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb61-3"><a href="#cb61-3" aria-hidden="true" tabindex="-1"></a><span class="co">// Two distinct lifetimes with no constraint.</span></span>
<span id="cb61-4"><a href="#cb61-4" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> F1 <span class="op">=</span> <span class="dt">void</span><span class="op">/(</span>a, b<span class="op">)(</span><span class="dt">int</span><span class="op">^/</span>a, <span class="dt">int</span><span class="op">^/</span>b<span class="op">)</span> safe;</span>
<span id="cb61-5"><a href="#cb61-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb61-6"><a href="#cb61-6" aria-hidden="true" tabindex="-1"></a><span class="co">// These are the same.</span></span>
<span id="cb61-7"><a href="#cb61-7" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> F2 <span class="op">=</span> <span class="dt">void</span><span class="op">/(</span>a, b where a <span class="op">:</span> b<span class="op">)(</span><span class="dt">int</span><span class="op">^/</span>a, <span class="dt">int</span><span class="op">^/</span>b<span class="op">)</span> safe;</span>
<span id="cb61-8"><a href="#cb61-8" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> F3 <span class="op">=</span> <span class="dt">void</span><span class="op">/(</span>a, b where b <span class="op">:</span> a<span class="op">)(</span><span class="dt">int</span><span class="op">^/</span>b, <span class="dt">int</span><span class="op">^/</span>a<span class="op">)</span> safe;</span>
<span id="cb61-9"><a href="#cb61-9" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>F2 <span class="op">==</span> F3<span class="op">)</span>;</span>
<span id="cb61-10"><a href="#cb61-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb61-11"><a href="#cb61-11" aria-hidden="true" tabindex="-1"></a><span class="co">// They differ from F1, due to the outlives-constraint.</span></span>
<span id="cb61-12"><a href="#cb61-12" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>F1 <span class="op">!=</span> F2<span class="op">)</span>;</span>
<span id="cb61-13"><a href="#cb61-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb61-14"><a href="#cb61-14" aria-hidden="true" tabindex="-1"></a><span class="co">// These are the same.</span></span>
<span id="cb61-15"><a href="#cb61-15" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> F4 <span class="op">=</span> <span class="dt">void</span><span class="op">/(</span>a, b where a <span class="op">:</span> b, b <span class="op">:</span> a<span class="op">)(</span><span class="dt">int</span><span class="op">^/</span>a, <span class="dt">int</span><span class="op">^/</span>b<span class="op">)</span> safe;</span>
<span id="cb61-16"><a href="#cb61-16" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> F5 <span class="op">=</span> <span class="dt">void</span><span class="op">/(</span>a<span class="op">)</span>                      <span class="op">(</span><span class="dt">int</span><span class="op">^/</span>a, <span class="dt">int</span><span class="op">^/</span>a<span class="op">)</span> safe;</span>
<span id="cb61-17"><a href="#cb61-17" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>F4 <span class="op">==</span> F5<span class="op">)</span>;</span>
<span id="cb61-18"><a href="#cb61-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb61-19"><a href="#cb61-19" aria-hidden="true" tabindex="-1"></a><span class="co">// They differ from F2, due to the constraint going both directions.</span></span>
<span id="cb61-20"><a href="#cb61-20" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>F2 <span class="op">!=</span> F4<span class="op">)</span>;</span></code></pre></div>
<p>Lifetime parameterizations are part of the function’s type. But
different textual parameterizations may still result in the same type!
<code class="sourceCode cpp">F1</code> and
<code class="sourceCode cpp">F2</code> have different parameterizations
and are different types. <code class="sourceCode cpp">F2</code> and
<code class="sourceCode cpp">F3</code> have different parameterizations
yet are the same type. Likewise, <code class="sourceCode cpp">F4</code>
and <code class="sourceCode cpp">F5</code> are the same type, even
though <code class="sourceCode cpp">F4</code> has two lifetime
parameters and two outlives constraints.</p>
<p>The compiler maps all non-dependent types to canonical types. When
comparing types for equality, it compares the pointers to their
canonical types. This is necessary to support typedefs and alias
templates that appear in functions–we need to strip away those
inessential details and get to the canonical types within. Lifetime
parameterizations the user declares also map to canonical
pameterizations.</p>
<p>Think about lifetime parameterizations as a directed graph. Lifetime
parameters are the nodes and outlives constraints define the edges. The
compiler finds the strongly connected components<span class="citation" data-cites="scc">[<a href="https://en.wikipedia.org/wiki/Strongly_connected_component" role="doc-biblioref">scc</a>]</span> of this graph. That is, it
identifies all cycles and reduces them into SCC nodes. In
<code class="sourceCode cpp">F4</code>, the
<code class="sourceCode cpp"><span class="op">/</span>a</code> and
<code class="sourceCode cpp"><span class="op">/</span>b</code> lifetime
parameters constrain one another and are collapsed into the same
strongly connected component. The canonical function type is encoded
using SCCs as lifetime parameters. After lifetime canonicalization both
<code class="sourceCode cpp">F4</code> and
<code class="sourceCode cpp">F5</code> map to the same canonical type
and therefore compare the same.</p>
<p>During the type relation pass that generates lifetime constraints for
function calls in the MIR, arguments and result object regions are
constrained to regions of the canonical type’s SCCs, rather than the
lifetime parameters of the declared type. This reduces the number of
regions the borrow checker solves for. But the big reason for this
process is to permit writing compatible functions when dealing with the
quirks of <a href="#lifetime-normalization">lifetime
normalization</a>.</p>
<h3 data-number="2.2.11" id="lifetimes-and-templates"><span class="header-section-number">2.2.11</span> Lifetimes and templates<a href="#lifetimes-and-templates" class="self-link"></a></h3>
<p>Templates are specially adapted to handle types with lifetime
binders. It’s important to understand how template lifetime parameters
are invented in order to understand how borrow checking fits with C++’s
late-checked generics.</p>
<p>In the current implementation, class templates feature a variation on
the type template parameter: <code class="sourceCode cpp"><span class="kw">typename</span> T<span class="op">+</span></code>
is a lifetime binder parameter. The class template invents an implicit
<em>template lifetime parameter</em> for each lifetime binder of the
argument’s type.</p>
<div class="sourceCode" id="cb62"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb62-1"><a href="#cb62-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T0<span class="op">+</span>, <span class="kw">typename</span> T1<span class="op">+&gt;</span></span>
<span id="cb62-2"><a href="#cb62-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Pair <span class="op">{</span></span>
<span id="cb62-3"><a href="#cb62-3" aria-hidden="true" tabindex="-1"></a>  T0 first;</span>
<span id="cb62-4"><a href="#cb62-4" aria-hidden="true" tabindex="-1"></a>  T1 second;</span>
<span id="cb62-5"><a href="#cb62-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb62-6"><a href="#cb62-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb62-7"><a href="#cb62-7" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> string_view<span class="op">/(</span>a<span class="op">)</span>;</span></code></pre></div>
<p>The <code class="sourceCode cpp">Pair</code> class template doesn’t
have any named lifetime parameters.
<code class="sourceCode cpp">string_view</code> has one named lifetime
parameter, which constrains the pointed-at string to outlive the view.
The specialization <code class="sourceCode cpp">Pair<span class="op">&lt;</span>string_view, string_view<span class="op">&gt;</span></code>
invents a template lifetime parameter for each view’s named lifetime
parameters. Call them <code class="sourceCode cpp">T0<span class="fl">.0</span><span class="er">.0</span></code>
and <code class="sourceCode cpp">T1<span class="fl">.0</span><span class="er">.0</span></code>.
<code class="sourceCode cpp">T0<span class="fl">.0</span></code> is for
the 0th parameter pack element of the template parameter
<code class="sourceCode cpp">T0</code>. <code class="sourceCode cpp">T0<span class="fl">.0</span><span class="er">.0</span></code>
is for the 0th lifetime binder in that type. If
<code class="sourceCode cpp">string_view</code> had a second named
parameter, the compiler would invent two more template lifetime
parameters: <code class="sourceCode cpp">T0<span class="fl">.0</span><span class="er">.1</span></code>
and <code class="sourceCode cpp">T1<span class="fl">.0</span><span class="er">.1</span></code>.</p>
<p>Consider the transformation when instantiating the definition of
<code class="sourceCode cpp">Pair<span class="op">&lt;</span>string_view<span class="op">/</span>a, string_view<span class="op">/</span>b<span class="op">&gt;</span></code>:</p>
<div class="sourceCode" id="cb63"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb63-1"><a href="#cb63-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;&gt;</span></span>
<span id="cb63-2"><a href="#cb63-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Pair<span class="op">/(</span>T0<span class="fl">.0</span><span class="er">.0</span>, T1<span class="fl">.0</span><span class="er">.0</span><span class="op">)&lt;</span>string_view<span class="op">/</span>T0<span class="fl">.0</span><span class="er">.0</span>, string_view<span class="op">/</span>T1<span class="fl">.0</span><span class="er">.0</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb63-3"><a href="#cb63-3" aria-hidden="true" tabindex="-1"></a>  string_view<span class="op">/</span>T0<span class="fl">.0</span><span class="er">.0</span> first;</span>
<span id="cb63-4"><a href="#cb63-4" aria-hidden="true" tabindex="-1"></a>  string_view<span class="op">/</span>T1<span class="fl">.0</span><span class="er">.0</span> second;</span>
<span id="cb63-5"><a href="#cb63-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>The compiler ignores the lifetime arguments
<code class="sourceCode cpp"><span class="op">/</span>a</code> and
<code class="sourceCode cpp"><span class="op">/</span>b</code> and
replaces them with the template lifetime parameters <code class="sourceCode cpp">T0<span class="fl">.0</span><span class="er">.0</span></code>
and <code class="sourceCode cpp">T1<span class="fl">.0</span><span class="er">.0</span></code>.
This transformation deduplicates template instantiations. We don’t want
to instantiate class templates for every lifetime argument on a template
argument type. That would be an incredible waste of compute and result
in enormous code bloat. Those lifetime arguments don’t carry data in the
same way as integer or string types do. Instead, lifetime arguments
define constraints on region variables between different function
parameters and result objects. Those constraints are an external concern
to the class template being specialized.</p>
<p>Since we replaced the named lifetime arguments with template lifetime
parameters during specialization of
<code class="sourceCode cpp">Pair</code>, you have to wonder, what
happened to
<code class="sourceCode cpp"><span class="op">/</span>a</code> and
<code class="sourceCode cpp"><span class="op">/</span>b</code>? They’re
factored out and stuck to the outside of the class template
specialization: <code class="sourceCode cpp">Pair<span class="op">&lt;</span>string_view, string_view<span class="op">&gt;/</span>a<span class="op">/</span>b</code>.
Since this specialized <code class="sourceCode cpp">Pair</code> has two
lifetime binders (those two template lifetime parameters), it needs to
bind two lifetime arguments. Safe C++ replaces lifetime arguments on
template arguments with invented template lifetime parameters and
reattaches the lifetime arguments to the specialization.</p>
<p>A class template’s instantiation doesn’t depend on the lifetimes of
its users. <code class="sourceCode cpp">std2<span class="op">::</span>vector<span class="op">&lt;</span>string_view<span class="op">/</span>a<span class="op">&gt;</span></code>
is transformed to <code class="sourceCode cpp">std2<span class="op">::</span>vector<span class="op">&lt;</span>string_view<span class="op">/</span>T0<span class="fl">.0</span><span class="er">.0</span><span class="op">&gt;/</span>a</code>.
<code class="sourceCode cpp">T0<span class="fl">.0</span><span class="er">.0</span></code>
is the implicitly declared lifetime parameter, which becomes the
lifetime argument on the template argument, and
<code class="sourceCode cpp"><span class="op">/</span>a</code> is the
user’s lifetime argument that was hoisted out of the
<em>template-argument-list</em> and appended to the class
specialization.</p>
<p>In the current safety model, this transformation only occurs for
bound lifetime template parameters with the <code class="sourceCode cpp"><span class="kw">typename</span> T<span class="op">+</span></code>
syntax. It’s not done for all template parameters, because that would
interfere with C++’s partial and explicit specialization facilities.</p>
<div class="sourceCode" id="cb64"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb64-1"><a href="#cb64-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T0, <span class="kw">typename</span> T1<span class="op">&gt;</span></span>
<span id="cb64-2"><a href="#cb64-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> is_same <span class="op">{</span></span>
<span id="cb64-3"><a href="#cb64-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">bool</span> value <span class="op">=</span> <span class="kw">false</span>;</span>
<span id="cb64-4"><a href="#cb64-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb64-5"><a href="#cb64-5" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb64-6"><a href="#cb64-6" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> is_same<span class="op">&lt;</span>T, T<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb64-7"><a href="#cb64-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">bool</span> value <span class="op">=</span> <span class="kw">true</span>;</span>
<span id="cb64-8"><a href="#cb64-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>Should <code class="sourceCode cpp">std<span class="op">::</span>is_same<span class="op">&lt;</span>string_view, string_view<span class="op">&gt;::</span>value</code>
be true or false? Of course it should be true. But if we invent template
lifetime parameters for each lifetime binder in the
<em>template-argument-list</em>, we’d get something like <code class="sourceCode cpp">std<span class="op">::</span>is_same<span class="op">&lt;</span>string_view<span class="op">/</span>T0<span class="fl">.0</span><span class="er">.0</span>, string_view<span class="op">/</span>T1<span class="fl">.0</span><span class="er">.0</span><span class="op">&gt;::</span>value</code>.
Those arguments are different types, and they wouldn’t match the partial
specialization.</p>
<p>When specializing a
<code class="sourceCode cpp"><span class="kw">typename</span> T</code>
template parameter, lifetimes are stripped from the template argument
types. They become unbound types. When specializing a <code class="sourceCode cpp"><span class="kw">typename</span> T<span class="op">+</span></code>
parameter, the compiler creates fully-bound types by implicitly adding
placeholder arguments
<code class="sourceCode cpp"><span class="op">/</span>_</code> whenever
needed. When a template specialization is matched, the lifetime
arguments are replaced with the specialization’s invented template
lifetime parameters and the original lifetime arguments are hoisted onto
the specialization.</p>
<p>You might want to think of this process as extending an electrical
circuit. The lifetime parameters outside of the class template are the
source, and their usage on the template arguments are the return. When
we instantiate a class template, the invented template lifetime
parameters become a new source, and their use as lifetime arguments in
the data members of the specialization are a new return. The old circuit
is connected to the new one, where the outer lifetime arguments lead
into the new template lifetime parameters.</p>
<div class="sourceCode" id="cb65"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb65-1"><a href="#cb65-1" aria-hidden="true" tabindex="-1"></a>Foo&lt;string_view/a&gt;</span>
<span id="cb65-2"><a href="#cb65-2" aria-hidden="true" tabindex="-1"></a>  Source: /a</span>
<span id="cb65-3"><a href="#cb65-3" aria-hidden="true" tabindex="-1"></a>  Return: string_view</span>
<span id="cb65-4"><a href="#cb65-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb65-5"><a href="#cb65-5" aria-hidden="true" tabindex="-1"></a>transforms to:</span>
<span id="cb65-6"><a href="#cb65-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb65-7"><a href="#cb65-7" aria-hidden="true" tabindex="-1"></a>Foo&lt;string_view/T0.0.0&gt;/a</span>
<span id="cb65-8"><a href="#cb65-8" aria-hidden="true" tabindex="-1"></a>  Source: /a</span>
<span id="cb65-9"><a href="#cb65-9" aria-hidden="true" tabindex="-1"></a>  Return: T0.0.0 (user-facing)</span>
<span id="cb65-10"><a href="#cb65-10" aria-hidden="true" tabindex="-1"></a>  Source: T0.0.0 (definition-facing)</span>
<span id="cb65-11"><a href="#cb65-11" aria-hidden="true" tabindex="-1"></a>  Return: string_view</span></code></pre></div>
<p>Because Rust doesn’t support partial or explicit specialization of
its generics, it has no corresponding distinction between type
parameters which bind lifetimes and type parameters which don’t. There’s
nothing like <code class="sourceCode cpp">is_same</code> that would be
confused by lifetime arguments in its operands.</p>
<p>Deciding when to use the <code class="sourceCode cpp"><span class="kw">typename</span> T<span class="op">+</span></code>
parameter kind on class templates will hopefully be straight-forward. If
the class template is a container and the parameter represents a thing
being contained, use the new syntax. If the class template exists for
metaprogramming, like the classes found in <code class="sourceCode cpp"><span class="op">&lt;</span>type_traits<span class="op">&gt;</span></code>,
it’s probably uninterested in bound lifetimes. Use the traditional
<code class="sourceCode cpp"><span class="kw">typename</span> T</code>
parameter kind.</p>
<p>The mechanism for generating template lifetime parameters feels
right, but its presentation to the user is still in flux. An alternative
treatment would optionally permit bound lifetimes in
<code class="sourceCode cpp"><span class="kw">typename</span> T</code>
template parameters, but require users to explicitly bind a placeholder
lifetime argument
<code class="sourceCode cpp"><span class="op">/</span>_</code> if they
want bound types:</p>
<div class="sourceCode" id="cb66"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb66-1"><a href="#cb66-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Types are unbound</span></span>
<span id="cb66-2"><a href="#cb66-2" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>std<span class="op">::</span>is_same_v<span class="op">&lt;</span><span class="dt">int</span><span class="op">^</span>, <span class="dt">int</span><span class="op">^&gt;</span> <span class="op">==</span> <span class="kw">true</span><span class="op">)</span>;</span>
<span id="cb66-3"><a href="#cb66-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb66-4"><a href="#cb66-4" aria-hidden="true" tabindex="-1"></a><span class="co">// Template arguments have bound placeholder lifetimes. These get replaced</span></span>
<span id="cb66-5"><a href="#cb66-5" aria-hidden="true" tabindex="-1"></a><span class="co">// with template lifetime parameters, and the resulting types compare</span></span>
<span id="cb66-6"><a href="#cb66-6" aria-hidden="true" tabindex="-1"></a><span class="co">// differently.</span></span>
<span id="cb66-7"><a href="#cb66-7" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>std<span class="op">::</span>is_same_v<span class="op">&lt;</span><span class="dt">int</span><span class="op">^/</span>_, <span class="dt">int</span><span class="op">^/</span>_<span class="op">&gt;</span> <span class="op">==</span> <span class="kw">false</span><span class="op">)</span>;</span>
<span id="cb66-8"><a href="#cb66-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb66-9"><a href="#cb66-9" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb66-10"><a href="#cb66-10" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Obj <span class="op">{</span></span>
<span id="cb66-11"><a href="#cb66-11" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Ill-formed if T has bound lifetimes.</span></span>
<span id="cb66-12"><a href="#cb66-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">(</span>std<span class="op">::</span>is_same_v<span class="op">&lt;</span>T, <span class="dt">int</span><span class="op">^&gt;)</span>;    <span class="co">// #1</span></span>
<span id="cb66-13"><a href="#cb66-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb66-14"><a href="#cb66-14" aria-hidden="true" tabindex="-1"></a>  <span class="co">// /0 strips lifetime arguments from types.</span></span>
<span id="cb66-15"><a href="#cb66-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">(</span>std<span class="op">::</span>is_same_v<span class="op">&lt;</span>T<span class="op">/</span><span class="dv">0</span>, <span class="dt">int</span><span class="op">^&gt;)</span>;  <span class="co">// #2</span></span>
<span id="cb66-16"><a href="#cb66-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb66-17"><a href="#cb66-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb66-18"><a href="#cb66-18" aria-hidden="true" tabindex="-1"></a>Obj<span class="op">&lt;</span><span class="dt">int</span><span class="op">^/</span>_<span class="op">&gt;</span> obj1;  <span class="co">// Ill-formed at #1. Well-formed at #2.</span></span>
<span id="cb66-19"><a href="#cb66-19" aria-hidden="true" tabindex="-1"></a>Obj<span class="op">&lt;</span><span class="dt">int</span><span class="op">^&gt;</span>   obj2;  <span class="co">// Well-formed at #1 and #2.</span></span></code></pre></div>
<h3 data-number="2.2.12" id="lifetime-normalization"><span class="header-section-number">2.2.12</span> Lifetime normalization<a href="#lifetime-normalization" class="self-link"></a></h3>
<p>Lifetime normalization conditions the lifetime parameters and
lifetime arguments on function declarations and function types. After
normalization, function parameters and return types have fully bound
lifetimes. Their lifetime arguments always refer to lifetime parameters
of the function, and not to those of any other scope, such as the
containing class.</p>
<p><em>Lifetime elision</em> assigns lifetime arguments to function
parameters and return types with unbound lifetimes. * If the type with
unbound lifetimes is the enclosing class of a member function, the
lifetime parameters of the enclosing class are used for elision. * If a
function parameter has unbound lifetimes, <em>elision lifetime
parameters</em> are invented to fully bind the function parameter. * If
a return type has unbound lifetimes and there is a
<code class="sourceCode cpp">self</code> parameter, it is assigned the
lifetime argument on the <code class="sourceCode cpp">self</code>
parameter, if there is just one, or elision is ill-formed. * If a return
type has unbound lifetimes and there is one lifetime parameter for the
whole function, the return type is assigned that, or elision is
ill-formed.</p>
<p>In addition to elision, lifetime normalization substitutes type
parameters in <em>outlives-constraints</em> with all corresponding
lifetime arguments of the template arguments.</p>
<div class="sourceCode" id="cb67"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb67-1"><a href="#cb67-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T1, <span class="kw">typename</span> T2, <span class="kw">typename</span> T3<span class="op">&gt;</span></span>
<span id="cb67-2"><a href="#cb67-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> func<span class="op">/(</span>where T1<span class="op">:</span><span class="kw">static</span>, T2<span class="op">:</span>T3<span class="op">)(</span>T1 x, T2 y, T3 Z<span class="op">)</span>;</span>
<span id="cb67-3"><a href="#cb67-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb67-4"><a href="#cb67-4" aria-hidden="true" tabindex="-1"></a><span class="op">&amp;</span>func<span class="op">&lt;</span><span class="dt">int</span><span class="op">^</span>, <span class="kw">const</span> string_view<span class="op">^</span>, <span class="dt">double</span><span class="op">&gt;</span>;</span></code></pre></div>
<p>During normalization of this function specialization, the
<em>outlives-constraint</em> is rebuilt with the substituted lifetime
arguments on its type parameters. The template lifetime parameter on
<code class="sourceCode cpp"><span class="dt">int</span><span class="op">^</span></code>
outlives <code class="sourceCode cpp"><span class="op">/</span><span class="kw">static</span></code>.
Both lifetime parameters bound on <code class="sourceCode cpp"><span class="kw">const</span> string_view<span class="op">^</span></code>
(one for the outer borrow, one on the string_view) outlive the lifetime
parameters bound on the
<code class="sourceCode cpp"><span class="dt">double</span></code>. But
<code class="sourceCode cpp"><span class="dt">double</span></code> isn’t
a lifetime binder. Since it contributes no lifetime parameters, the
<code class="sourceCode cpp">T2<span class="op">:</span>T3</code> type
constraint is dropped during normalization.</p>
<h2 data-number="2.3" id="explicit-mutation"><span class="header-section-number">2.3</span> Explicit mutation<a href="#explicit-mutation" class="self-link"></a></h2>
<p>Reference binding convention is important in the context of borrow
checking. Const and non-const borrows differ by more than just
constness. By the law of exclusivity, users are allowed multiple live
shared borrows, but only one live mutable borrow. C++’s convention of
always preferring non-const references would tie the borrow checker into
knots, as mutable borrows don’t permit aliasing. This is one reason why
there’s no way to borrow check existing C++ code: standard conversions
are too permissive and contribute to mutable aliasing.</p>
<p>Unlike in Standard C++, expressions in this object model can have
reference types. Naming a reference object yields an lvalue expression
with reference type, rather than implicitly dereferencing the reference
and giving you an lvalue to the pointed-at thing. Dereferencing legacy
references is unsafe. If references were implicitly dereferenced, you’d
never be able to use them in safe contexts. In Safe C++, references are
more like pointers, and may be passed around in safe contexts, but not
dereferenced.</p>
<p>Rather than binding the mutable overload of functions by default,
Safe C++ prefers binding const overloads. It prefers binding shared
borrows to mutable borrows. Shared borrows are less likely to bring
borrow checker errors. To improve reference binding precision, the
relocation object model takes a new approach to references. Standard
conversions bind const borrows and const lvalue references to lvalues of
the same type, as they always have. But standard conversions won’t bind
mutable borrows and mutable lvalue references. Those require an
opt-in.</p>
<div class="sourceCode" id="cb68"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb68-1"><a href="#cb68-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Obj <span class="op">{</span></span>
<span id="cb68-2"><a href="#cb68-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> <span class="dt">int</span><span class="op">&amp;</span> func<span class="op">()</span> <span class="kw">const</span>;   <span class="co">// #1</span></span>
<span id="cb68-3"><a href="#cb68-3" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span><span class="op">&amp;</span> func<span class="op">()</span>;         <span class="co">// #2</span></span>
<span id="cb68-4"><a href="#cb68-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb68-5"><a href="#cb68-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb68-6"><a href="#cb68-6" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> func<span class="op">(</span>Obj obj<span class="op">)</span> <span class="op">{</span></span>
<span id="cb68-7"><a href="#cb68-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// In ISO C++, calls overload #2.</span></span>
<span id="cb68-8"><a href="#cb68-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">// In Safe C++, calls overload #1.</span></span>
<span id="cb68-9"><a href="#cb68-9" aria-hidden="true" tabindex="-1"></a>  obj<span class="op">.</span>func<span class="op">()</span>;</span>
<span id="cb68-10"><a href="#cb68-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb68-11"><a href="#cb68-11" aria-hidden="true" tabindex="-1"></a>  <span class="co">// In Safe C++, these all call overload #2.</span></span>
<span id="cb68-12"><a href="#cb68-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">(&amp;</span>obj<span class="op">).</span>func<span class="op">()</span>;</span>
<span id="cb68-13"><a href="#cb68-13" aria-hidden="true" tabindex="-1"></a>  obj<span class="op">&amp;.</span>func<span class="op">()</span>;</span>
<span id="cb68-14"><a href="#cb68-14" aria-hidden="true" tabindex="-1"></a>  mut obj<span class="op">.</span>func<span class="op">()</span>;</span>
<span id="cb68-15"><a href="#cb68-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>In Safe C++, the standard conversion will not bind a mutable borrow
or mutable lvalue reference. During overload resolution for <code class="sourceCode cpp">obj<span class="op">.</span>func<span class="op">()</span></code>,
candidate #2 fails, because the compiler can’t bind the object parameter
type
<code class="sourceCode cpp">Obj<span class="op">&amp;</span></code> to
the object expression <code class="sourceCode cpp">lvalue Obj</code>.
But candidate #1 is viable, because the standard conversion can still
bind the object parameter type <code class="sourceCode cpp"><span class="kw">const</span> Obj<span class="op">&amp;</span></code>
to the object expression
<code class="sourceCode cpp">lvalue Obj</code>.</p>
<p>The subsequent statements call candidate #1 by explicitly requesting
mutation.
<code class="sourceCode cpp"><span class="op">&amp;</span>obj</code> is
syntax for creating a <code class="sourceCode cpp">prvalue Obj<span class="op">&amp;</span></code>
from the <code class="sourceCode cpp">lvalue Obj</code> operand. We can
call the <code class="sourceCode cpp">func</code> member function on
that reference. <code class="sourceCode cpp">obj<span class="op">&amp;.</span>func<span class="op">()</span></code>
uses a special postfix syntax that alleviates the need for parentheses.
Finally, the <code class="sourceCode cpp">mut</code> keyword puts the
remaining operators of the <em>cast-expression</em> into the <a href="#the-mutable-context"><em>mutable context</em></a>. In the mutable
context, standard conversions to mutable borrows and mutable lvalue
references are enabled. Overload resolution finds both candidates #1 and
#2 viable, and chooses #2 because the mutable reference outranks the
const reference.</p>
<p>Here’s a list of <em>unary-operators</em> for taking borrows, lvalue
and rvalue references, and pointers to lvalues.</p>
<ul>
<li><code class="sourceCode cpp"><span class="op">^</span>x</code> -
mutable borrow to <code class="sourceCode cpp">x</code></li>
<li><code class="sourceCode cpp"><span class="op">^</span><span class="kw">const</span> x</code>
- shared borrow to <code class="sourceCode cpp">x</code></li>
<li><code class="sourceCode cpp"><span class="op">&amp;</span>x</code> -
lvalue reference to <code class="sourceCode cpp">x</code> (convertible
to pointer)</li>
<li><code class="sourceCode cpp"><span class="op">&amp;</span><span class="kw">const</span> x</code>
- const lvalue reference to <code class="sourceCode cpp">x</code></li>
<li><code class="sourceCode cpp"><span class="op">&amp;&amp;</span>x</code>
- rvalue reference to <code class="sourceCode cpp">x</code></li>
<li><code class="sourceCode cpp">addr x</code> - pointer to
<code class="sourceCode cpp">x</code></li>
<li><code class="sourceCode cpp">addr <span class="kw">const</span> x</code>
- const pointer to <code class="sourceCode cpp">x</code></li>
</ul>
<p>While the motivation of this design is to pacify the borrow checker
by preferring shared reference binding, a desirable side effect is that
<strong>all mutations are explicit</strong>. You don’t have to wonder
about side-effects. If you’re passing arguments to a function, and you
don’t see <code class="sourceCode cpp">mut</code>,
<code class="sourceCode cpp"><span class="op">^</span></code>,
<code class="sourceCode cpp"><span class="op">&amp;</span></code> or
<code class="sourceCode cpp"><span class="op">&amp;&amp;</span></code>
before it, you know the argument won’t be modified by that function.</p>
<div class="sourceCode" id="cb69"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb69-1"><a href="#cb69-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb69-2"><a href="#cb69-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;iostream&gt;</span></span>
<span id="cb69-3"><a href="#cb69-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb69-4"><a href="#cb69-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f1<span class="op">(</span><span class="dt">int</span><span class="op">^)</span>;</span>
<span id="cb69-5"><a href="#cb69-5" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f2<span class="op">(</span><span class="kw">const</span> <span class="dt">int</span><span class="op">^)</span>;</span>
<span id="cb69-6"><a href="#cb69-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb69-7"><a href="#cb69-7" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f3<span class="op">(</span><span class="dt">int</span><span class="op">&amp;)</span>;</span>
<span id="cb69-8"><a href="#cb69-8" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f4<span class="op">(</span><span class="kw">const</span> <span class="dt">int</span><span class="op">&amp;)</span>;</span>
<span id="cb69-9"><a href="#cb69-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb69-10"><a href="#cb69-10" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f5<span class="op">(</span><span class="dt">int</span><span class="op">&amp;&amp;)</span>;</span>
<span id="cb69-11"><a href="#cb69-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb69-12"><a href="#cb69-12" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb69-13"><a href="#cb69-13" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> x <span class="op">=</span> <span class="dv">1</span>;</span>
<span id="cb69-14"><a href="#cb69-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb69-15"><a href="#cb69-15" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Explicit ^ for mut borrow required.</span></span>
<span id="cb69-16"><a href="#cb69-16" aria-hidden="true" tabindex="-1"></a>  f1<span class="op">(^</span>x<span class="op">)</span>;</span>
<span id="cb69-17"><a href="#cb69-17" aria-hidden="true" tabindex="-1"></a>  f1<span class="op">(</span>mut x<span class="op">)</span>;</span>
<span id="cb69-18"><a href="#cb69-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb69-19"><a href="#cb69-19" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Standard conversion or explicit ^const for shared borrow.</span></span>
<span id="cb69-20"><a href="#cb69-20" aria-hidden="true" tabindex="-1"></a>  f2<span class="op">(</span>x<span class="op">)</span>;</span>
<span id="cb69-21"><a href="#cb69-21" aria-hidden="true" tabindex="-1"></a>  f2<span class="op">(^</span><span class="kw">const</span> x<span class="op">)</span>;</span>
<span id="cb69-22"><a href="#cb69-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb69-23"><a href="#cb69-23" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Explicit &amp; for lvalue ref required.</span></span>
<span id="cb69-24"><a href="#cb69-24" aria-hidden="true" tabindex="-1"></a>  f3<span class="op">(&amp;</span>x<span class="op">)</span>;</span>
<span id="cb69-25"><a href="#cb69-25" aria-hidden="true" tabindex="-1"></a>  f3<span class="op">(</span>mut x<span class="op">)</span>;</span>
<span id="cb69-26"><a href="#cb69-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb69-27"><a href="#cb69-27" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Standard conversion or explicit &amp;const for const lvalue ref.</span></span>
<span id="cb69-28"><a href="#cb69-28" aria-hidden="true" tabindex="-1"></a>  f4<span class="op">(</span>x<span class="op">)</span>;</span>
<span id="cb69-29"><a href="#cb69-29" aria-hidden="true" tabindex="-1"></a>  f4<span class="op">(&amp;</span><span class="kw">const</span> x<span class="op">)</span>;</span>
<span id="cb69-30"><a href="#cb69-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb69-31"><a href="#cb69-31" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Explicit rvalue ref.</span></span>
<span id="cb69-32"><a href="#cb69-32" aria-hidden="true" tabindex="-1"></a>  f5<span class="op">(&amp;&amp;</span>x<span class="op">)</span>;</span>
<span id="cb69-33"><a href="#cb69-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb69-34"><a href="#cb69-34" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Explicit &amp; for non-const lvalue reference operands.</span></span>
<span id="cb69-35"><a href="#cb69-35" aria-hidden="true" tabindex="-1"></a>  <span class="op">&amp;</span>std<span class="op">::</span>cout<span class="op">&lt;&lt;</span> <span class="st">&quot;Hello mutation</span><span class="sc">\n</span><span class="st">&quot;</span>;</span>
<span id="cb69-36"><a href="#cb69-36" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>In Rust, types and declarations are const by default. In C++, they’re
mutable by default. But by supporting standard conversions to const
references, reference binding in Safe C++ is less noisy than the Rust
equivalent, while being no less precise.</p>
<div class="sourceCode" id="cb70"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb70-1"><a href="#cb70-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Rust:</span></span>
<span id="cb70-2"><a href="#cb70-2" aria-hidden="true" tabindex="-1"></a>f<span class="op">(&amp;</span>mut x<span class="op">)</span>;    <span class="co">// Pass by mutable borrow.</span></span>
<span id="cb70-3"><a href="#cb70-3" aria-hidden="true" tabindex="-1"></a>f<span class="op">(&amp;</span>x<span class="op">)</span>;        <span class="co">// Pass by shared borrow.</span></span>
<span id="cb70-4"><a href="#cb70-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb70-5"><a href="#cb70-5" aria-hidden="true" tabindex="-1"></a><span class="co">// C++:</span></span>
<span id="cb70-6"><a href="#cb70-6" aria-hidden="true" tabindex="-1"></a>f<span class="op">(^</span>x<span class="op">)</span>;        <span class="co">// Pass by mutable borrow.</span></span>
<span id="cb70-7"><a href="#cb70-7" aria-hidden="true" tabindex="-1"></a>f<span class="op">(</span>x<span class="op">)</span>;         <span class="co">// Pass by shared borrow.</span></span>
<span id="cb70-8"><a href="#cb70-8" aria-hidden="true" tabindex="-1"></a>f<span class="op">(^</span><span class="kw">const</span> x<span class="op">)</span>;  <span class="co">// Extra verbose -- call attention to it.</span></span>
<span id="cb70-9"><a href="#cb70-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb70-10"><a href="#cb70-10" aria-hidden="true" tabindex="-1"></a>f<span class="op">(&amp;</span>x<span class="op">)</span>;        <span class="co">// Pass by mutable lvalue ref.</span></span>
<span id="cb70-11"><a href="#cb70-11" aria-hidden="true" tabindex="-1"></a>f<span class="op">(</span>x<span class="op">)</span>;         <span class="co">// Pass by const lvalue ref.</span></span>
<span id="cb70-12"><a href="#cb70-12" aria-hidden="true" tabindex="-1"></a>f<span class="op">(&amp;</span><span class="kw">const</span> x<span class="op">)</span>;  <span class="co">// Extra verbose -- call attention to it.</span></span></code></pre></div>
<h3 data-number="2.3.1" id="the-mutable-context"><span class="header-section-number">2.3.1</span> The mutable context<a href="#the-mutable-context" class="self-link"></a></h3>
<p>The mutable context is the preferred way to express mutation. In a
sense it returns Safe C++ to legacy C++’s default binding behavior. Use
it at the start of a <em>cast-expression</em> and the mutable context
lasts for all subsequent higher-precedence operations. In the mutable
context, standard conversion may bind mutable borrows and mutable lvalue
references to lvalue operands.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/mut.cxx"><strong>mut.cxx</strong></a>
– <a href="https://godbolt.org/z/7YPoc4d8b">(Compiler Explorer)</a></p>
<div class="sourceCode" id="cb71"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb71-1"><a href="#cb71-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb71-2"><a href="#cb71-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;std2.h&gt;</span></span>
<span id="cb71-3"><a href="#cb71-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb71-4"><a href="#cb71-4" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb71-5"><a href="#cb71-5" aria-hidden="true" tabindex="-1"></a>  std2<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">size_t</span><span class="op">&gt;</span> A <span class="op">{</span> <span class="op">}</span>, B <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb71-6"><a href="#cb71-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb71-7"><a href="#cb71-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Get a shared borrow to an element in B.</span></span>
<span id="cb71-8"><a href="#cb71-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">// The borrow is live until it is loaded from below.</span></span>
<span id="cb71-9"><a href="#cb71-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> <span class="dt">size_t</span><span class="op">^</span> b <span class="op">=</span> B<span class="op">[</span><span class="dv">0</span><span class="op">]</span>;</span>
<span id="cb71-10"><a href="#cb71-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb71-11"><a href="#cb71-11" aria-hidden="true" tabindex="-1"></a>  <span class="co">// A[0] is in the mutable context, so A[0] is the mutable operator[].</span></span>
<span id="cb71-12"><a href="#cb71-12" aria-hidden="true" tabindex="-1"></a>  <span class="co">// B[0] is outside the mutable context, so B[0] is the const operator[].</span></span>
<span id="cb71-13"><a href="#cb71-13" aria-hidden="true" tabindex="-1"></a>  <span class="co">// No borrow checking error.</span></span>
<span id="cb71-14"><a href="#cb71-14" aria-hidden="true" tabindex="-1"></a>  mut A<span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">+=</span> B<span class="op">[</span><span class="dv">0</span><span class="op">]</span>;</span>
<span id="cb71-15"><a href="#cb71-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb71-16"><a href="#cb71-16" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Keep b live.</span></span>
<span id="cb71-17"><a href="#cb71-17" aria-hidden="true" tabindex="-1"></a>  <span class="dt">size_t</span> x <span class="op">=</span> <span class="op">*</span>b;</span>
<span id="cb71-18"><a href="#cb71-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Write the <code class="sourceCode cpp">mut</code> token before the
<em>cast-expression</em> you want to mutate. <em>cast-expressions</em>
include high-precedence unary expressions. Lower-precedence binary
expressions aren’t in the scope of the mutable context. In this example,
the mutable context applies only to the left-hand side of the
assignment. <code class="sourceCode cpp">A<span class="op">[</span><span class="dv">0</span><span class="op">]</span></code>
chooses the mutable overload of <code class="sourceCode cpp">vector<span class="op">::</span><span class="kw">operator</span><span class="op">[]</span></code>
and <code class="sourceCode cpp">B<span class="op">[</span><span class="dv">0</span><span class="op">]</span></code>
chooses the const overload of <code class="sourceCode cpp">vector<span class="op">::</span><span class="kw">operator</span><span class="op">[]</span></code>.
The example takes a shared borrow on
<code class="sourceCode cpp">B</code> and uses it at the end of
<code class="sourceCode cpp">main</code> in order to trap a mutable
borrow to <code class="sourceCode cpp">B</code> at the statement with
the compound assignment.</p>
<p><code class="sourceCode cpp">mut A<span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">+=</span> B<span class="op">[</span><span class="dv">0</span><span class="op">]</span></code>
mutable binds <code class="sourceCode cpp">A</code> to get the mutable
overload of <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">[]</span></code>.
<code class="sourceCode cpp">B</code> is on the right-hand side of the
assignment, which is outside the scope of the mutable context.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/mut2.cxx"><strong>mut2.cxx</strong></a>
– <a href="https://godbolt.org/z/db35zexYP">(Compiler Explorer)</a></p>
<div class="sourceCode" id="cb72"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb72-1"><a href="#cb72-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb72-2"><a href="#cb72-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;std2.h&gt;</span></span>
<span id="cb72-3"><a href="#cb72-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb72-4"><a href="#cb72-4" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb72-5"><a href="#cb72-5" aria-hidden="true" tabindex="-1"></a>  std2<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">size_t</span><span class="op">&gt;</span> A <span class="op">{</span> <span class="op">}</span>, B <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb72-6"><a href="#cb72-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb72-7"><a href="#cb72-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Get a shared borrow to an element in B.</span></span>
<span id="cb72-8"><a href="#cb72-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">// The borrow is live until it is loaded from below.</span></span>
<span id="cb72-9"><a href="#cb72-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> <span class="dt">size_t</span><span class="op">^</span> b <span class="op">=</span> B<span class="op">[</span><span class="dv">0</span><span class="op">]</span>;</span>
<span id="cb72-10"><a href="#cb72-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb72-11"><a href="#cb72-11" aria-hidden="true" tabindex="-1"></a>  <span class="co">// A is in the mutable context for its operator[] call.</span></span>
<span id="cb72-12"><a href="#cb72-12" aria-hidden="true" tabindex="-1"></a>  <span class="co">// B is not in the mutable conetxt for its operator[] call.</span></span>
<span id="cb72-13"><a href="#cb72-13" aria-hidden="true" tabindex="-1"></a>  <span class="co">// No borrow checker error.</span></span>
<span id="cb72-14"><a href="#cb72-14" aria-hidden="true" tabindex="-1"></a>  mut A<span class="op">[</span>B<span class="op">[</span><span class="dv">0</span><span class="op">]]</span> <span class="op">+=</span> <span class="dv">1</span>;</span>
<span id="cb72-15"><a href="#cb72-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb72-16"><a href="#cb72-16" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Keep b live.</span></span>
<span id="cb72-17"><a href="#cb72-17" aria-hidden="true" tabindex="-1"></a>  <span class="dt">size_t</span> x <span class="op">=</span> <span class="op">*</span>b;</span>
<span id="cb72-18"><a href="#cb72-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The mutable context is entered at the start of a
<em>cast-expression</em> with the
<code class="sourceCode cpp">mut</code> token. It exists for subsequent
high-precedence <em>unary-expression</em>, <em>postfix-expression</em>
and <em>primary-expression</em> operations. But it doesn’t transer into
subexpressions of these. The index operand of the subscript operator
matches the <em>expression-list</em> production, which is lower
precedence than <em>cast-expression</em>, so it’s not entered with the
mutable context. <code class="sourceCode cpp">B<span class="op">[</span><span class="dv">0</span><span class="op">]</span></code>
is bound with a shared borrow. One would have to write <code class="sourceCode cpp">mut A<span class="op">[</span>mut B<span class="op">[</span><span class="dv">0</span><span class="op">]]</span> <span class="op">+=</span> <span class="dv">1</span>;</code>
to bind a mutable borrow on both objects.</p>
<p>The mutable context explicitly marks points of mutation while letting
standard conversions worry about the details. Its intent is to reduce
cognitive load on developers compared with using the reference
operators.</p>
<h2 data-number="2.4" id="relocation-object-model"><span class="header-section-number">2.4</span> Relocation object model<a href="#relocation-object-model" class="self-link"></a></h2>
<p>A core enabling feature of Safe C++ is its new object model. It
supports relocation/destructive move of local objects, which is
necessary for satisfying <a href="#type-safety">type safety</a>.</p>
<p>In Rust, objects are <em>relocated by default</em>. Implicit
relocation is too surprising for C++ users. We’re more likely to have
raw pointers and legacy references tracking objects, and you don’t want
to pull the storage out from under them, at least not without some clear
token in the source code. That’s why Safe C++ includes
<em>rel-expression</em> and <em>cpy-expression</em>.</p>
<ul>
<li><code class="sourceCode cpp">rel x</code> - relocate
<code class="sourceCode cpp">x</code> into a new value.
<code class="sourceCode cpp">x</code> is set as uninitialized.</li>
<li><code class="sourceCode cpp">cpy x</code> - copy construct
<code class="sourceCode cpp">x</code> into a new value.
<code class="sourceCode cpp">x</code> remains initialized.</li>
</ul>
<p>In line with C++’s goals of <em>zero-cost abstractions</em>, we want
to make it easy for users to choose the more efficient option between
relocaton and copy. If the expression’s type is trivially copyable and
trivially destructible, it’ll initialize a copy from an lvalue.
Otherwise, the compiler prompts for a
<code class="sourceCode cpp">rel</code> or
<code class="sourceCode cpp">cpy</code> token to resolve the copy
initialization. You’re not going to accidentally hit the slow path or
the mutable path. Opt into mutation. Opt into non-trivial copies. opy,
or do you want to relocate?</p>
<p>You’ve noticed the nonsense spellings for some of these keywords. Why
not call them <code class="sourceCode cpp">relocate</code>,
<code class="sourceCode cpp">copy</code> and
<code class="sourceCode cpp">drop</code>? Alternative token spelling
avoids shadowing these common identifiers and improves results when
searching code or the web.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/move.cxx"><strong>move.cxx</strong></a>
– <a href="https://godbolt.org/z/5bsfnfG16">(Compiler Explorer)</a></p>
<div class="sourceCode" id="cb73"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb73-1"><a href="#cb73-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb73-2"><a href="#cb73-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;std2.h&gt;</span></span>
<span id="cb73-3"><a href="#cb73-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb73-4"><a href="#cb73-4" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb73-5"><a href="#cb73-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Objects start off uninitialized. A use of an uninitialized</span></span>
<span id="cb73-6"><a href="#cb73-6" aria-hidden="true" tabindex="-1"></a>  <span class="co">// object is ill-formed.</span></span>
<span id="cb73-7"><a href="#cb73-7" aria-hidden="true" tabindex="-1"></a>  std2<span class="op">::</span>string s;</span>
<span id="cb73-8"><a href="#cb73-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb73-9"><a href="#cb73-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Require explicit initialization.</span></span>
<span id="cb73-10"><a href="#cb73-10" aria-hidden="true" tabindex="-1"></a>  s <span class="op">=</span> std2<span class="op">::</span>string<span class="op">(</span><span class="st">&quot;Hello &quot;</span><span class="op">)</span>;</span>
<span id="cb73-11"><a href="#cb73-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb73-12"><a href="#cb73-12" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Require explicit mutation.</span></span>
<span id="cb73-13"><a href="#cb73-13" aria-hidden="true" tabindex="-1"></a>  mut s<span class="op">.</span>append<span class="op">(</span><span class="st">&quot;World&quot;</span><span class="op">)</span>;</span>
<span id="cb73-14"><a href="#cb73-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb73-15"><a href="#cb73-15" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Require explicit relocation.</span></span>
<span id="cb73-16"><a href="#cb73-16" aria-hidden="true" tabindex="-1"></a>  std2<span class="op">::</span>string s2 <span class="op">=</span> rel s;  <span class="co">// Now s is uninitialized.</span></span>
<span id="cb73-17"><a href="#cb73-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb73-18"><a href="#cb73-18" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Require explicit non-trivial copy.</span></span>
<span id="cb73-19"><a href="#cb73-19" aria-hidden="true" tabindex="-1"></a>  std2<span class="op">::</span>string s3 <span class="op">=</span> cpy s2;</span>
<span id="cb73-20"><a href="#cb73-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb73-21"><a href="#cb73-21" aria-hidden="true" tabindex="-1"></a>  <span class="co">// `Hello World`.</span></span>
<span id="cb73-22"><a href="#cb73-22" aria-hidden="true" tabindex="-1"></a>  println<span class="op">(</span>s3<span class="op">)</span>;</span>
<span id="cb73-23"><a href="#cb73-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Initialization, copy, move and mutation are explicit. Deleting the
<code class="sourceCode cpp">rel</code> token in this example breaks
translation and prompts for guidance:</p>
<div class="sourceCode" id="cb74"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb74-1"><a href="#cb74-1" aria-hidden="true" tabindex="-1"></a>  std2::string s2 = s;  // Now s is uninitialized. </span>
<span id="cb74-2"><a href="#cb74-2" aria-hidden="true" tabindex="-1"></a>                    ^</span>
<span id="cb74-3"><a href="#cb74-3" aria-hidden="true" tabindex="-1"></a>implicit copy from lvalue std2::string not allowed</span>
<span id="cb74-4"><a href="#cb74-4" aria-hidden="true" tabindex="-1"></a>specify cpy or rel or add the [[safety::copy]] attribute</span></code></pre></div>
<p>A standard conversion from <code class="sourceCode cpp">lvalue std2<span class="op">::</span>string</code>
to
<code class="sourceCode cpp">std2<span class="op">::</span>string</code>
is found. But without the user’s help, the compiler doesn’t know how
satsify the conversion: does it call the copy constructor, which is
expensive, or does it perform relocation, which is cheap but changes the
operand by ending its scope?</p>
<h3 data-number="2.4.1" id="tuples-arrays-and-slices"><span class="header-section-number">2.4.1</span> Tuples, arrays and slices<a href="#tuples-arrays-and-slices" class="self-link"></a></h3>
<p>Using an uninitialized or potentially uninitialized object raises a
compile-time error. But initialization analysis only accounts for the
state of local variables that are directly named and not part of a
dereference. Local objects and their subobjects are <em>owned
places</em>. Initialization analysis allocates flags for owned places,
so that it can track their initialization status and error when there’s
a use of a place that’s not <em>definitely initialized</em>. It’s not
possible for the compiler to chase through references and function calls
to find initialization data for objects potentially owned by other
functions–that’s a capability of <em>whole program analysis</em>, which
is beyond of the scope of this proposal.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/rel1.cxx"><strong>rel1.cxx</strong></a>
– <a href="https://godbolt.org/z/8nGo59E1v">(Compiler Explorer)</a></p>
<div class="sourceCode" id="cb75"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb75-1"><a href="#cb75-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb75-2"><a href="#cb75-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;tuple&gt;</span></span>
<span id="cb75-3"><a href="#cb75-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb75-4"><a href="#cb75-4" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Pair <span class="op">{</span></span>
<span id="cb75-5"><a href="#cb75-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> x, y;</span>
<span id="cb75-6"><a href="#cb75-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb75-7"><a href="#cb75-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb75-8"><a href="#cb75-8" aria-hidden="true" tabindex="-1"></a>Pair g <span class="op">{</span> <span class="dv">10</span>, <span class="dv">20</span> <span class="op">}</span>;</span>
<span id="cb75-9"><a href="#cb75-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb75-10"><a href="#cb75-10" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb75-11"><a href="#cb75-11" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Relocate from an std::tuple element.</span></span>
<span id="cb75-12"><a href="#cb75-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> tup <span class="op">=</span> std<span class="op">::</span>make_tuple<span class="op">(</span><span class="dv">5</span>, <span class="fl">1.619</span><span class="op">)</span>;</span>
<span id="cb75-13"><a href="#cb75-13" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> x <span class="op">=</span> rel <span class="op">*</span>get<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;(&amp;</span>tup<span class="op">)</span>;</span>
<span id="cb75-14"><a href="#cb75-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb75-15"><a href="#cb75-15" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Relocate from runtime subscript.</span></span>
<span id="cb75-16"><a href="#cb75-16" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> data<span class="op">[</span><span class="dv">5</span><span class="op">]</span> <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb75-17"><a href="#cb75-17" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> index <span class="op">=</span> <span class="dv">1</span>;</span>
<span id="cb75-18"><a href="#cb75-18" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> y <span class="op">=</span> rel data<span class="op">[</span>index<span class="op">]</span>;</span>
<span id="cb75-19"><a href="#cb75-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb75-20"><a href="#cb75-20" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Relocate from subobject of a global.</span></span>
<span id="cb75-21"><a href="#cb75-21" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> gy <span class="op">=</span> rel g<span class="op">.</span>y;</span>
<span id="cb75-22"><a href="#cb75-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb11"><pre class="sourceCode txt"><code class="sourceCode default"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>$ circle rel1.cxx</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>safety: rel1.cxx:13:15</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>  int x = rel *get&lt;0&gt;(&amp;tup);</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>              ^</span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>rel operand does not refer to an owned place</span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>an owned place is a local variable or subobject of a local variable</span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>the place involves a dereference of int&amp;</span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>safety: rel1.cxx:18:19</span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>  int y = rel data[index];</span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>                  ^</span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>rel operand does not refer to an owned place</span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a>an owned place is a local variable or subobject of a local variable</span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a>the place involves a subscript of int[5]</span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true" tabindex="-1"></a>safety: rel1.cxx:21:17</span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true" tabindex="-1"></a>  int gy = rel g.y;</span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true" tabindex="-1"></a>                ^</span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true" tabindex="-1"></a>rel operand does not refer to an owned place</span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true" tabindex="-1"></a>an owned place is a local variable or subobject of a local variable</span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true" tabindex="-1"></a>g is a non-local variable declared at rel1.cxx:8:6</span>
<span id="cb11-22"><a href="#cb11-22" aria-hidden="true" tabindex="-1"></a>Pair g { 10, 20 };</span>
<span id="cb11-23"><a href="#cb11-23" aria-hidden="true" tabindex="-1"></a>     ^</span></code></pre></div>
<p>This example shows that you can’t relocate through the reference
returned from
<code class="sourceCode cpp">std<span class="op">::</span>get</code>.
You can’t relocate through a dynamic subscript of an array. You can’t
relocate the subobject of a global variable. You can only relocate or
drop <em>owned places</em>.</p>
<p>If we can’t relocate through a reference, how do we relocate through
elements of
<code class="sourceCode cpp">std<span class="op">::</span>tuple</code>,
<code class="sourceCode cpp">std<span class="op">::</span>array</code>
or
<code class="sourceCode cpp">std<span class="op">::</span>variant</code>?
Unless those become magic types with special compiler support, you
can’t. Those standard containers only provide access to their elements
through accessor functions which return references. Subobjects behind
references are not <em>owned places</em>.</p>
<p>We address the defects in C++’s algebraic types by including new
first-class tuple, array and <a href="#choice-types">choice</a> types.
Safe C++ is still compatible with legacy types, but due to their
non-local element access, relocation from their subobjects is not
currently implemented. Relocation is important to type safety, because
many types prohibit default states, making C++-style move semantics
impossible. Either relocate your object, or put it in an
<code class="sourceCode cpp">optional</code> from which it can be
unwrapped.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/tuple1.cxx"><strong>tuple1.cxx</strong></a>
– <a href="https://godbolt.org/z/4hq7Eb86x">(Compiler Explorer)</a></p>
<div class="sourceCode" id="cb76"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb76-1"><a href="#cb76-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb76-2"><a href="#cb76-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;std2.h&gt;</span><span class="pp">          </span><span class="co">// Pull in the definition of std2::tuple.</span></span>
<span id="cb76-3"><a href="#cb76-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-4"><a href="#cb76-4" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> T0 <span class="op">=</span> <span class="op">()</span>;             <span class="co">// Zero-length tuple type.</span></span>
<span id="cb76-5"><a href="#cb76-5" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> T1 <span class="op">=</span> <span class="op">(</span><span class="dt">int</span>, <span class="op">)</span>;        <span class="co">// One-length tuple type.</span></span>
<span id="cb76-6"><a href="#cb76-6" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> T2 <span class="op">=</span> <span class="op">(</span><span class="dt">int</span>, <span class="dt">double</span><span class="op">)</span>;  <span class="co">// Longer tuples type.</span></span>
<span id="cb76-7"><a href="#cb76-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-8"><a href="#cb76-8" aria-hidden="true" tabindex="-1"></a><span class="co">// Nest at your leisure.</span></span>
<span id="cb76-9"><a href="#cb76-9" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> T3 <span class="op">=</span> <span class="op">(((</span><span class="dt">int</span>, <span class="dt">double</span><span class="op">)</span>, <span class="dt">float</span><span class="op">)</span>, <span class="dt">char</span><span class="op">)</span>;</span>
<span id="cb76-10"><a href="#cb76-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-11"><a href="#cb76-11" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb76-12"><a href="#cb76-12" aria-hidden="true" tabindex="-1"></a>   <span class="co">// Zero-length tuple expression.</span></span>
<span id="cb76-13"><a href="#cb76-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> t0 <span class="op">=</span> <span class="op">(</span>,<span class="op">)</span>;</span>
<span id="cb76-14"><a href="#cb76-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">(</span>T0 <span class="op">==</span> <span class="kw">decltype</span><span class="op">(</span>t0<span class="op">))</span>;</span>
<span id="cb76-15"><a href="#cb76-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-16"><a href="#cb76-16" aria-hidden="true" tabindex="-1"></a>  <span class="co">// One-length tuple expression.</span></span>
<span id="cb76-17"><a href="#cb76-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> t1 <span class="op">=</span> <span class="op">(</span><span class="dv">4</span>, <span class="op">)</span>;</span>
<span id="cb76-18"><a href="#cb76-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">(</span>T1 <span class="op">==</span> <span class="kw">decltype</span><span class="op">(</span>t1<span class="op">))</span>;</span>
<span id="cb76-19"><a href="#cb76-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-20"><a href="#cb76-20" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Longer tuple expression.</span></span>
<span id="cb76-21"><a href="#cb76-21" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> t2 <span class="op">=</span> <span class="op">(</span><span class="dv">5</span>, <span class="fl">3.14</span><span class="op">)</span>;</span>
<span id="cb76-22"><a href="#cb76-22" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">(</span>T2 <span class="op">==</span> <span class="kw">decltype</span><span class="op">(</span>t2<span class="op">))</span>;</span>
<span id="cb76-23"><a href="#cb76-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-24"><a href="#cb76-24" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Nest tuples.</span></span>
<span id="cb76-25"><a href="#cb76-25" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> t3 <span class="op">=</span> <span class="op">(((</span><span class="dv">1</span>, <span class="fl">1.618</span><span class="op">)</span>, <span class="fl">3.3</span><span class="bu">f</span><span class="op">)</span>, <span class="ch">&#39;T&#39;</span><span class="op">)</span>;</span>
<span id="cb76-26"><a href="#cb76-26" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">(</span>T3 <span class="op">==</span> <span class="kw">decltype</span><span class="op">(</span>t3<span class="op">))</span>;</span>
<span id="cb76-27"><a href="#cb76-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-28"><a href="#cb76-28" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Access the 1.618 double field:</span></span>
<span id="cb76-29"><a href="#cb76-29" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> x <span class="op">=</span> t3<span class="fl">.0</span><span class="er">.0</span><span class="fl">.1</span>;</span>
<span id="cb76-30"><a href="#cb76-30" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">(</span><span class="dt">double</span> <span class="op">==</span> <span class="kw">decltype</span><span class="op">(</span>x<span class="op">))</span>;</span>
<span id="cb76-31"><a href="#cb76-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The new first-class tuple type is syntaxed with comma-separated lists
of types inside parentheses. Tuple expressions are noted with
comma-separated lists of expressions inside parentheses. You can nest
them. You can access elements of tuple expressions by chaining indices
together with dots. Tuple fields are accessed with the customary special
tuple syntax: just write the element index after a dot, eg
<code class="sourceCode cpp">tup<span class="fl">.0</span></code>.</p>
<p>Use <code class="sourceCode cpp">circle <span class="op">-</span>print<span class="op">-</span>mir</code>
to dump the MIR of this program.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode txt"><code class="sourceCode default"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>   15  Assign _4.1 = 84</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>   16  Commit _4 (((int, double), float), char)</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>   17  InstStart _5 double</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>   18  Assign _5 = use _4.0.0.1</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>   19  InstEnd _5</span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>   20  InstEnd _4</span></code></pre></div>
<p>The assignment <code class="sourceCode cpp">t3<span class="fl">.0</span><span class="er">.0</span><span class="fl">.1</span></code>
lowers to <code class="sourceCode cpp">_4<span class="fl">.0</span><span class="er">.0</span><span class="fl">.1</span></code>.
This is a place name of a local variable. Importantly, it doesn’t
involve dereferences, unlike the result of an
<code class="sourceCode cpp">std<span class="op">::</span>get</code>
call. It’s an <em>owned place</em> which the compiler is able to
relocate out of.</p>
<p>C++’s native array decays to pointers and doesn’t support
pass-by-value semantics.
<code class="sourceCode cpp">std<span class="op">::</span>array</code>
encapsulates arrays to fix these problems and provides an <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">[]</span></code>
API for consistent subscripting syntax. But
<code class="sourceCode cpp">std<span class="op">::</span>array</code>
is broken for our purposes. Since <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">[]</span></code>
returns a reference, the
<code class="sourceCode cpp">std<span class="op">::</span>array</code>’s
elements are not <em>owned places</em> and can’t be relocated out
of.</p>
<p>Safe C++ introduces a first-class pass-by-value array type <code class="sourceCode cpp"><span class="op">[</span>T; N<span class="op">]</span></code>
and a first-class slice companion type <code class="sourceCode cpp"><span class="op">[</span>T; dyn<span class="op">]</span></code>.
Subobjects of both the old and new array types with constant indices are
<em>owned places</em> and support relocation.</p>
<p>Slices have dynamic length and are <em>incomplete types</em>. You may
form borrows, references or pointers to slices and access through those.
These are called <em>fat pointers</em> and are 16 bytes on 64-bit
platforms. The data pointer is accompanied by a length field.</p>
<p>The new array type, the slice type and the legacy builtin array type
panic on out-of-bounds subscripts. They exhibit bounds safety in the new
object model. Use <a href="#unsafe-subscripts">unsafe subscripts</a> to
suppress the runtime bounds check.</p>
<p>Making
<code class="sourceCode cpp">std<span class="op">::</span>pair</code>,
<code class="sourceCode cpp">std<span class="op">::</span>tuple</code>
and
<code class="sourceCode cpp">std<span class="op">::</span>array</code>
magic types with native support for relocation is on the short list of
language improvements. We hope to incorporate this functionality for the
next revision of this proposal. In the meantime, the first-class
replacement types provide us with a convenient path forward for
developing the safe standard library.</p>
<h3 data-number="2.4.2" id="operator-rel"><span class="header-section-number">2.4.2</span>
<code class="sourceCode cpp"><span class="kw">operator</span> rel</code><a href="#operator-rel" class="self-link"></a></h3>
<p>Safe C++ introduces a new special member function, the <em>relocation
constructor</em>, written <code class="sourceCode cpp"><span class="kw">operator</span> rel<span class="op">(</span>T<span class="op">)</span></code>,
for all class types. Using the <em>rel-expression</em> invokes the
relocation constructor. The relocation constructor exists to bridge
C++11’s move semantics model with Safe C++’s relocation model.
Relocation constructors can be:</p>
<ul>
<li>User defined - manually relocate the operand into the new object.
This can be used for fixing internal addresses, like those used to
implement sentinels in standard linked lists and maps.</li>
<li><code class="sourceCode cpp"><span class="op">=</span> trivial</code>
- Trivially copyable types are already trivially relocatable. But other
types may be trivially relocatable as well, like
<code class="sourceCode cpp">box</code>,
<code class="sourceCode cpp">unique_ptr</code>,
<code class="sourceCode cpp">rc</code>,
<code class="sourceCode cpp">arc</code> and
<code class="sourceCode cpp">shared_ptr</code>.</li>
<li><code class="sourceCode cpp"><span class="op">=</span> <span class="cf">default</span></code>
- A defaulted or implicitly declared relocation constructor is
implemented by the compiler with one of three strategies: types with
safe destructors are trivially relocated; aggregate types use
member-wise relocation; and other types are move-constructed into the
new data, and the old operand is destroyed.</li>
<li><code class="sourceCode cpp"><span class="op">=</span> <span class="kw">delete</span></code>
- A deleted relocation constructor <em>pins</em> a type. Objects of that
type can’t be relocated. A <code class="sourceCode cpp">rel<span class="op">-</span>expression</code> is
a SFINAE failure. Rust uses its
<code class="sourceCode cpp">std<span class="op">::</span>Pin</code><span class="citation" data-cites="pin">[<a href="https://doc.rust-lang.org/std/pin/index.html" role="doc-biblioref">pin</a>]</span> pin type as a container for structs
with with address-sensitive states. That’s an option with Safe C++’s
deleted relocation constructors. Or, users can write user-defined
relocation constructors to update address-sensitive states.</li>
</ul>
<p>Relocation constructors are always noexcept. It’s used to implement
the drop-and-replace semantics of assignment expressions. If a
relocation constructor was throwing, it might leave objects involved in
drop-and-replace in illegal uninitialized states. An uncaught exception
in a user-defined or defaulted relocation constructor will panic and
terminate.</p>
<p><span class="citation" data-cites="P1144R11">[<a href="https://wg21.link/p1144r11" role="doc-biblioref">P1144R11</a>]</span> proposes tests to
automatically classify types that should exhibit trivial relocation
based on other properties. The Safe C++ model will need to work through
the same issues, but with a richer set of language features to
consider.</p>
<h2 data-number="2.5" id="choice-types"><span class="header-section-number">2.5</span> Choice types<a href="#choice-types" class="self-link"></a></h2>
<p>The new <code class="sourceCode cpp">choice</code> type is a type
safe discriminated union. It’s equivalent to Rust’s
<code class="sourceCode cpp"><span class="kw">enum</span></code> type.
Choice types contain a list of alternatives, each with an optional
payload type. <code class="sourceCode cpp">choice</code> does not
replace C++’s
<code class="sourceCode cpp"><span class="kw">enum</span></code> type.
It’s a different type with different capabilities.</p>
<blockquote>
<p>For an enumeration whose underlying type is fixed, the values of the
enumeration are the values of the underlying type. Otherwise, the values
of the enumeration are the values representable by a hypothetical
integer type with minimal width M such that all enumerators can be
represented. The width of the smallest bit-field large enough to hold
all the values of the enumeration type is M. <em>It is possible to
define an enumeration that has values not defined by any of its
enumerators.</em></p>
<p>– <cite><a href="https://eel.is/c++draft/dcl.enum#8">dcl.enum</a></cite></p>
</blockquote>
<p>It’s not possible to safely exhaustiveness checking on C++ enums,
because enums may hold values that aren’t among their enumerators.</p>
<p><code class="sourceCode cpp">choice</code> types are more rigorously
defined. They may only hold values that are specified alternatives. That
makes them much easier to reason about, and permits the compiler perform
exhaustiveness checking. There’s no safe conversion between choice types
and their underlying types; programmers must use choice initializers to
create new choice objects and <em>match-expressions</em> to interrogate
them.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/choice.cxx"><strong>choice.cxx</strong></a></p>
<div class="sourceCode" id="cb77"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb77-1"><a href="#cb77-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb77-2"><a href="#cb77-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb77-3"><a href="#cb77-3" aria-hidden="true" tabindex="-1"></a><span class="co">// An enum-like choice that has alternatives but no payloads.</span></span>
<span id="cb77-4"><a href="#cb77-4" aria-hidden="true" tabindex="-1"></a><span class="co">// Unlike enums, it is not permitted to cast between C1 and its underlying</span></span>
<span id="cb77-5"><a href="#cb77-5" aria-hidden="true" tabindex="-1"></a><span class="co">// integral type.</span></span>
<span id="cb77-6"><a href="#cb77-6" aria-hidden="true" tabindex="-1"></a>choice C1 <span class="op">{</span></span>
<span id="cb77-7"><a href="#cb77-7" aria-hidden="true" tabindex="-1"></a>  A, B, C,</span>
<span id="cb77-8"><a href="#cb77-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb77-9"><a href="#cb77-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb77-10"><a href="#cb77-10" aria-hidden="true" tabindex="-1"></a><span class="co">// A choice type with payloads for each alternative.</span></span>
<span id="cb77-11"><a href="#cb77-11" aria-hidden="true" tabindex="-1"></a>choice C2 <span class="op">{</span></span>
<span id="cb77-12"><a href="#cb77-12" aria-hidden="true" tabindex="-1"></a>  i8<span class="op">(</span><span class="dt">int8_t</span><span class="op">)</span>,</span>
<span id="cb77-13"><a href="#cb77-13" aria-hidden="true" tabindex="-1"></a>  i16<span class="op">(</span><span class="dt">int16_t</span><span class="op">)</span>,</span>
<span id="cb77-14"><a href="#cb77-14" aria-hidden="true" tabindex="-1"></a>  i32<span class="op">(</span><span class="dt">int32_t</span><span class="op">)</span>,</span>
<span id="cb77-15"><a href="#cb77-15" aria-hidden="true" tabindex="-1"></a>  i64<span class="op">(</span><span class="dt">int64_t</span><span class="op">)</span>,</span>
<span id="cb77-16"><a href="#cb77-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb77-17"><a href="#cb77-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb77-18"><a href="#cb77-18" aria-hidden="true" tabindex="-1"></a><span class="co">// A choice type with mixed payload and no-payload alternatives.</span></span>
<span id="cb77-19"><a href="#cb77-19" aria-hidden="true" tabindex="-1"></a>choice C3 <span class="op">{</span></span>
<span id="cb77-20"><a href="#cb77-20" aria-hidden="true" tabindex="-1"></a>  <span class="co">// default allowed once per choice, on a no-payload alternative.</span></span>
<span id="cb77-21"><a href="#cb77-21" aria-hidden="true" tabindex="-1"></a>  <span class="cf">default</span> none,</span>
<span id="cb77-22"><a href="#cb77-22" aria-hidden="true" tabindex="-1"></a>  i<span class="op">(</span><span class="dt">int</span><span class="op">)</span>,</span>
<span id="cb77-23"><a href="#cb77-23" aria-hidden="true" tabindex="-1"></a>  f<span class="op">(</span><span class="dt">float</span><span class="op">)</span>,</span>
<span id="cb77-24"><a href="#cb77-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb77-25"><a href="#cb77-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb77-26"><a href="#cb77-26" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb77-27"><a href="#cb77-27" aria-hidden="true" tabindex="-1"></a>  <span class="co">// choice-initializer uses scope resolution to name the alternative.</span></span>
<span id="cb77-28"><a href="#cb77-28" aria-hidden="true" tabindex="-1"></a>  C1 x1 <span class="op">=</span> C1<span class="op">::</span>B<span class="op">()</span>;</span>
<span id="cb77-29"><a href="#cb77-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb77-30"><a href="#cb77-30" aria-hidden="true" tabindex="-1"></a>  <span class="co">// abbreviated-choice-name infers the choice type from the lhs.</span></span>
<span id="cb77-31"><a href="#cb77-31" aria-hidden="true" tabindex="-1"></a>  <span class="co">// If there&#39;s no payload type, using () is optional.</span></span>
<span id="cb77-32"><a href="#cb77-32" aria-hidden="true" tabindex="-1"></a>  C1 x2 <span class="op">=</span> <span class="op">.</span>B<span class="op">()</span>;</span>
<span id="cb77-33"><a href="#cb77-33" aria-hidden="true" tabindex="-1"></a>  C1 x3 <span class="op">=</span> <span class="op">.</span>B;</span>
<span id="cb77-34"><a href="#cb77-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb77-35"><a href="#cb77-35" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Create choice objects with initializers.</span></span>
<span id="cb77-36"><a href="#cb77-36" aria-hidden="true" tabindex="-1"></a>  C2 y1 <span class="op">=</span> C2<span class="op">::</span>i32<span class="op">(</span><span class="dv">55</span><span class="op">)</span>;</span>
<span id="cb77-37"><a href="#cb77-37" aria-hidden="true" tabindex="-1"></a>  C2 y2 <span class="op">=</span> <span class="op">.</span>i32<span class="op">(</span><span class="dv">55</span><span class="op">)</span>;</span>
<span id="cb77-38"><a href="#cb77-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb77-39"><a href="#cb77-39" aria-hidden="true" tabindex="-1"></a>  <span class="co">// If there&#39;s a defaulted alternative, the choice type has a default</span></span>
<span id="cb77-40"><a href="#cb77-40" aria-hidden="true" tabindex="-1"></a>  <span class="co">// initializer that makes an instance with that value.</span></span>
<span id="cb77-41"><a href="#cb77-41" aria-hidden="true" tabindex="-1"></a>  C3 z1 <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb77-42"><a href="#cb77-42" aria-hidden="true" tabindex="-1"></a>  C3 z2 <span class="op">=</span> C3<span class="op">()</span>;</span>
<span id="cb77-43"><a href="#cb77-43" aria-hidden="true" tabindex="-1"></a>  C3 z3 <span class="op">=</span> C3<span class="op">::</span>none<span class="op">()</span>;</span>
<span id="cb77-44"><a href="#cb77-44" aria-hidden="true" tabindex="-1"></a>  C3 z4 <span class="op">=</span> <span class="op">.</span>none;</span>
<span id="cb77-45"><a href="#cb77-45" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Construct a <code class="sourceCode cpp">choice</code> type using the
qualified <em>choice-initializer</em> syntax <code class="sourceCode cpp">ChoiceName<span class="op">::</span>Alternative<span class="op">(</span>args<span class="op">)</span></code>.
In the context of copy initialization, which include return statements,
<em>mem-initializer</em>, function arguments, and so on, use the
<em>abbreviated-choice-name</em>,
<code class="sourceCode cpp"><span class="op">.</span>Alternative</code>
or <code class="sourceCode cpp"><span class="op">.</span>Alternative<span class="op">(</span>args<span class="op">)</span></code>
to create a choice object with less typing. The choice type is inferred
from type being initialized.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode cxx"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">+,</span> <span class="kw">class</span> E<span class="op">+&gt;</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>choice expected <span class="op">{</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">[[</span><span class="at">safety</span><span class="op">::</span><span class="at">unwrap</span><span class="op">]]</span> ok<span class="op">(</span>T<span class="op">),</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>  err<span class="op">(</span>E<span class="op">);</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>  T unwrap<span class="op">(</span>self<span class="op">)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> match<span class="op">(</span>self<span class="op">)</span> <span class="op">-&gt;</span> T <span class="op">{</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>      <span class="op">.</span>ok<span class="op">(</span>t<span class="op">)</span>  <span class="op">=&gt;</span> rel t<span class="op">;</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>      <span class="op">.</span>err<span class="op">(</span>e<span class="op">)</span> <span class="op">=&gt;</span> panic<span class="op">(</span><span class="st">&quot;</span><span class="sc">{}</span><span class="st"> is err&quot;</span><span class="op">.</span>format<span class="op">(</span>expected<span class="op">~</span>string<span class="op">));</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">+&gt;</span></span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a>choice optional</span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a>  <span class="cf">default</span> none<span class="op">,</span></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a>  <span class="op">[[</span><span class="at">safety</span><span class="op">::</span><span class="at">unwrap</span><span class="op">]]</span> some<span class="op">(</span>T<span class="op">);</span></span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> E<span class="op">&gt;</span></span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a>  expected<span class="op">&lt;</span>T<span class="op">,</span> E<span class="op">&gt;</span> ok_or<span class="op">(</span>self<span class="op">,</span> E e<span class="op">)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> match<span class="op">(</span>self<span class="op">)</span> <span class="op">-&gt;</span> expected<span class="op">&lt;</span>T<span class="op">,</span> E<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb13-23"><a href="#cb13-23" aria-hidden="true" tabindex="-1"></a>      <span class="op">.</span>some<span class="op">(</span>t<span class="op">)</span> <span class="op">=&gt;</span> <span class="op">.</span>ok<span class="op">(</span>rel t<span class="op">);</span></span>
<span id="cb13-24"><a href="#cb13-24" aria-hidden="true" tabindex="-1"></a>      <span class="op">.</span>none    <span class="op">=&gt;</span> <span class="op">.</span>err<span class="op">(</span>rel e<span class="op">);</span></span>
<span id="cb13-25"><a href="#cb13-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb13-26"><a href="#cb13-26" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb13-27"><a href="#cb13-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-28"><a href="#cb13-28" aria-hidden="true" tabindex="-1"></a>  T expect<span class="op">(</span>self<span class="op">,</span> str msg<span class="op">)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb13-29"><a href="#cb13-29" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> match<span class="op">(</span>self<span class="op">)</span> <span class="op">-&gt;</span> T <span class="op">{</span></span>
<span id="cb13-30"><a href="#cb13-30" aria-hidden="true" tabindex="-1"></a>      <span class="op">.</span>some<span class="op">(</span>t<span class="op">)</span> <span class="op">=&gt;</span> rel t<span class="op">;</span></span>
<span id="cb13-31"><a href="#cb13-31" aria-hidden="true" tabindex="-1"></a>      <span class="op">.</span>none    <span class="op">=&gt;</span> panic<span class="op">(</span>msg<span class="op">);</span></span>
<span id="cb13-32"><a href="#cb13-32" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb13-33"><a href="#cb13-33" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb13-34"><a href="#cb13-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-35"><a href="#cb13-35" aria-hidden="true" tabindex="-1"></a>  T unwrap<span class="op">(</span>self<span class="op">)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb13-36"><a href="#cb13-36" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> match<span class="op">(</span>self<span class="op">)</span> <span class="op">-&gt;</span> T <span class="op">{</span></span>
<span id="cb13-37"><a href="#cb13-37" aria-hidden="true" tabindex="-1"></a>      <span class="op">.</span>some<span class="op">(</span>t<span class="op">)</span> <span class="op">=&gt;</span> rel t<span class="op">;</span></span>
<span id="cb13-38"><a href="#cb13-38" aria-hidden="true" tabindex="-1"></a>      <span class="op">.</span>none    <span class="op">=&gt;</span> panic<span class="op">(</span><span class="st">&quot;</span><span class="sc">{}</span><span class="st"> is none&quot;</span><span class="op">.</span>format<span class="op">(</span>optional<span class="op">~</span>string<span class="op">));</span></span>
<span id="cb13-39"><a href="#cb13-39" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb13-40"><a href="#cb13-40" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb13-41"><a href="#cb13-41" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-42"><a href="#cb13-42" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span>
<span id="cb13-43"><a href="#cb13-43" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span></code></pre></div>
<p>Rust uses traits to extend data types with new member functions
outside of their definitions. Safe C++ doesn’t have that capability, so
it’s important that choice types support member functions directly.
These member functions may internalize pattern matching on their
<code class="sourceCode cpp">self</code> parameters, improving the
ergonomics of these type-safe variants.</p>
<p><code class="sourceCode cpp">std2<span class="op">::</span>expected</code> and
<code class="sourceCode cpp">std2<span class="op">::</span>optional</code> are
choice types important to the safe standard library. They implement a
suite of member functions as a convenience.</p>
<h3 data-number="2.5.1" id="pattern-matching"><span class="header-section-number">2.5.1</span> Pattern matching<a href="#pattern-matching" class="self-link"></a></h3>
<p>The <em>match-expression</em> in Safe C++ offers much the same
capabilities as the pattern matching implemented in C# and Swift and
proposed for C++ in <span class="citation" data-cites="P2688R1">[<a href="https://wg21.link/p2688r1" role="doc-biblioref">P2688R1</a>]</span>. But the requirements of borrow
checking and relocation make it most similar to Rust’s feature. Pattern
matching is the only way to access alternatives of choice types. Pattern
matching important in achieving Safe C++’s type safety goals.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/match1.cxx"><strong>match1.cxx</strong></a>
– <a href="https://godbolt.org/z/q1xsMzMKP">(Compiler Explorer)</a></p>
<div class="sourceCode" id="cb78"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb78-1"><a href="#cb78-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb78-2"><a href="#cb78-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;std2.h&gt;</span></span>
<span id="cb78-3"><a href="#cb78-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb78-4"><a href="#cb78-4" aria-hidden="true" tabindex="-1"></a>choice Primitive <span class="op">{</span></span>
<span id="cb78-5"><a href="#cb78-5" aria-hidden="true" tabindex="-1"></a>  i8<span class="op">(</span><span class="dt">int8_t</span><span class="op">)</span>,</span>
<span id="cb78-6"><a href="#cb78-6" aria-hidden="true" tabindex="-1"></a>  i16<span class="op">(</span><span class="dt">int16_t</span><span class="op">)</span>,</span>
<span id="cb78-7"><a href="#cb78-7" aria-hidden="true" tabindex="-1"></a>  i32<span class="op">(</span><span class="dt">int32_t</span><span class="op">)</span>,</span>
<span id="cb78-8"><a href="#cb78-8" aria-hidden="true" tabindex="-1"></a>  i64<span class="op">(</span><span class="dt">int64_t</span><span class="op">)</span>,</span>
<span id="cb78-9"><a href="#cb78-9" aria-hidden="true" tabindex="-1"></a>  i64_2<span class="op">(</span><span class="dt">int64_t</span><span class="op">)</span>,</span>
<span id="cb78-10"><a href="#cb78-10" aria-hidden="true" tabindex="-1"></a>  i64_3<span class="op">(</span><span class="dt">int64_t</span><span class="op">)</span>,</span>
<span id="cb78-11"><a href="#cb78-11" aria-hidden="true" tabindex="-1"></a>  pair<span class="op">(</span><span class="dt">int</span>, <span class="dt">int</span><span class="op">)</span>,</span>
<span id="cb78-12"><a href="#cb78-12" aria-hidden="true" tabindex="-1"></a>  s<span class="op">(</span>std2<span class="op">::</span>string<span class="op">)</span></span>
<span id="cb78-13"><a href="#cb78-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb78-14"><a href="#cb78-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb78-15"><a href="#cb78-15" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> test<span class="op">(</span>Primitive obj<span class="op">)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb78-16"><a href="#cb78-16" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> match<span class="op">(</span>obj<span class="op">)</span> <span class="op">{</span></span>
<span id="cb78-17"><a href="#cb78-17" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Match 1, 2, 4, or 8 for either i32 or i64.</span></span>
<span id="cb78-18"><a href="#cb78-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span>i32<span class="op">(</span><span class="dv">1</span><span class="op">|</span><span class="dv">2</span><span class="op">|</span><span class="dv">4</span><span class="op">|</span><span class="dv">8</span><span class="op">)</span> <span class="op">|</span> <span class="op">.</span>i64<span class="op">(</span><span class="dv">1</span><span class="op">|</span><span class="dv">2</span><span class="op">|</span><span class="dv">4</span><span class="op">|</span><span class="dv">8</span><span class="op">)</span>   <span class="op">=&gt;</span> <span class="dv">1</span>;</span>
<span id="cb78-19"><a href="#cb78-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb78-20"><a href="#cb78-20" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Match less than 0. ..a is half-open interval.</span></span>
<span id="cb78-21"><a href="#cb78-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span>i32<span class="op">(.</span><span class="fl">.0</span><span class="op">)</span>                       <span class="op">=&gt;</span> <span class="dv">2</span>;</span>
<span id="cb78-22"><a href="#cb78-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb78-23"><a href="#cb78-23" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Match 100 to 200 inclusive. ..= is closed interval.</span></span>
<span id="cb78-24"><a href="#cb78-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span>i32<span class="op">(</span><span class="fl">100.</span><span class="er">.</span><span class="op">=</span><span class="dv">200</span><span class="op">)</span>                 <span class="op">=&gt;</span> <span class="dv">3</span>;</span>
<span id="cb78-25"><a href="#cb78-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb78-26"><a href="#cb78-26" aria-hidden="true" tabindex="-1"></a>    <span class="co">// variant-style access. Match all alternatives with</span></span>
<span id="cb78-27"><a href="#cb78-27" aria-hidden="true" tabindex="-1"></a>    <span class="co">// a `int64_t` type. In this case, i64, i64_2 or i64_3</span></span>
<span id="cb78-28"><a href="#cb78-28" aria-hidden="true" tabindex="-1"></a>    <span class="co">// matches the pattern.</span></span>
<span id="cb78-29"><a href="#cb78-29" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span><span class="dt">int64_t</span><span class="op">}(</span><span class="dv">500</span> <span class="op">|</span> <span class="fl">1000.</span><span class="er">.2000</span><span class="op">)</span>     <span class="op">=&gt;</span> <span class="dv">4</span>;</span>
<span id="cb78-30"><a href="#cb78-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb78-31"><a href="#cb78-31" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Match a 2-tuple/aggregate. Bind declarations x and y to</span></span>
<span id="cb78-32"><a href="#cb78-32" aria-hidden="true" tabindex="-1"></a>    <span class="co">// the tuple elements. The match-guard passes when x &gt; y.</span></span>
<span id="cb78-33"><a href="#cb78-33" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span>pair<span class="op">([</span>x, y<span class="op">])</span> <span class="cf">if</span> <span class="op">(</span>x <span class="op">&gt;</span> y<span class="op">)</span>        <span class="op">=&gt;</span> <span class="dv">5</span>;</span>
<span id="cb78-34"><a href="#cb78-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb78-35"><a href="#cb78-35" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Match everything else.</span></span>
<span id="cb78-36"><a href="#cb78-36" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Comment the wildcard for an exhaustiveness error.</span></span>
<span id="cb78-37"><a href="#cb78-37" aria-hidden="true" tabindex="-1"></a>    _                               <span class="op">=&gt;</span> <span class="dv">6</span>;</span>
<span id="cb78-38"><a href="#cb78-38" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb78-39"><a href="#cb78-39" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>A <em>match-expression</em>’s operand is an expression of class,
choice, array, slice, arithmetic, builtin vector or builtin matrix type.
The <em>match-specifier</em> is populated with a set of
<em>match-clauses</em>. Each <em>match-clause</em> has a
<em>pattern</em> on the left, an optional <em>match-guard</em> in the
middle, and a <em>match-body</em> after the
<code class="sourceCode cpp"><span class="op">=&gt;</span></code>
token.</p>
<p>A match is rich in the kind of patterns it supports:</p>
<ul>
<li><strong>structured pattern</strong> <code class="sourceCode cpp"><span class="op">[</span>p1, p2<span class="op">]</span></code>
- Matches subobjects of aggregates and C++ types that implement the
<code class="sourceCode cpp">tuple_size</code>/<code class="sourceCode cpp">tuple_element</code>
customization point. These are useful when destructuring Safe C++’s
first-class tuple and array types. Nest the patterns to destructure
multiple levels of subobjects. The syntax of this pattern corresponds to
structured bindings and aggregate initializers.</li>
<li><strong>designated pattern</strong> <code class="sourceCode cpp"><span class="op">[</span>x<span class="op">:</span> p1, y<span class="op">:</span> p2<span class="op">]</span></code>
- Matches subobjects of aggregates by member name rather than ordinal.
The syntax of this pattern corresponds to designated bindings and
designated initializers.</li>
<li><strong>choice pattern</strong>
<code class="sourceCode cpp"><span class="op">.</span>alt</code> or
<code class="sourceCode cpp"><span class="op">.</span>alt<span class="op">(</span>p<span class="op">)</span></code>
- Matches choice alternatives. If the choice alternative has a payload
type, the <code class="sourceCode cpp"><span class="op">.</span>alt<span class="op">(</span>p<span class="op">)</span></code>
syntax opens a pattern on its payload.</li>
<li><strong>variant pattern</strong> <code class="sourceCode cpp"><span class="op">{</span>type<span class="op">}</span></code>
or <code class="sourceCode cpp"><span class="op">{</span>type<span class="op">}(</span>p<span class="op">)</span></code>
- Matches all choice alternatives with a payload type of <em>type</em>.
The <code class="sourceCode cpp"><span class="op">{</span>type<span class="op">}(</span>p<span class="op">)</span></code>
syntax opens a pattern on the payload.</li>
<li><strong>wildcard pattern</strong>
<code class="sourceCode cpp">_</code> Matches any pattern. These
correspond to the
<code class="sourceCode cpp"><span class="cf">default</span></code> case
of a <em>switch-statement</em> and may be required to satisfy a
<em>match-expression</em>’s exhaustiveness requirement.</li>
<li><strong>rest pattern</strong> -
<code class="sourceCode cpp"><span class="op">..</span></code> Matches
any number of elements. Use inside structured patterns to produce
patterns on the beginning or end elements. Also used to supports
patterns on slice operands.</li>
<li><strong>binding declaration</strong> <em>binding-mode</em>
<code class="sourceCode cpp">decl</code> - Bind a declaration to the
pattern’s operand. There are six binding modes: <em>default</em>,
<code class="sourceCode cpp">cpy</code>,
<code class="sourceCode cpp">rel</code>,
<code class="sourceCode cpp"><span class="op">^</span></code> for
mutable borrows, <code class="sourceCode cpp"><span class="op">^</span><span class="kw">const</span></code>
for shared borrows and
<code class="sourceCode cpp"><span class="op">&amp;</span></code> for
lvalue references.</li>
<li><strong>test pattern</strong> - Name a constant literal or constant
expression inside parentheses. These can be formed into range
expressions with an operand on either or both sides of
<code class="sourceCode cpp"><span class="op">..</span></code> or
<code class="sourceCode cpp"><span class="op">..=</span></code>. The
current operand of the match must match the test pattern to go to the
body.</li>
<li><strong>disjunction pattern</strong>
<code class="sourceCode cpp">p1 <span class="op">|</span> p2</code> -
Separate patterns with the disjunction operator
<code class="sourceCode cpp"><span class="op">|</span></code>.</li>
</ul>
<p>This example uses choice, test, variant, binding, disjunction and
wildcard patterns. The wildcard pattern at the end proves
exhaustiveness.</p>
<p><a href="https://github.com/cppalliance/safe-cpp/blob/master/proposal/match2.cxx"><strong>match2.cxx</strong></a>
– <a href="https://godbolt.org/z/h1rhajorG">(Compiler Explorer)</a></p>
<div class="sourceCode" id="cb79"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb79-1"><a href="#cb79-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">feature on safety</span></span>
<span id="cb79-2"><a href="#cb79-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;std2.h&gt;</span></span>
<span id="cb79-3"><a href="#cb79-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb79-4"><a href="#cb79-4" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> <span class="kw">namespace</span> std2;</span>
<span id="cb79-5"><a href="#cb79-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb79-6"><a href="#cb79-6" aria-hidden="true" tabindex="-1"></a>choice Primitive <span class="op">{</span></span>
<span id="cb79-7"><a href="#cb79-7" aria-hidden="true" tabindex="-1"></a>  i8<span class="op">(</span><span class="dt">int8_t</span><span class="op">)</span>,</span>
<span id="cb79-8"><a href="#cb79-8" aria-hidden="true" tabindex="-1"></a>  u8<span class="op">(</span><span class="dt">uint8_t</span><span class="op">)</span>,</span>
<span id="cb79-9"><a href="#cb79-9" aria-hidden="true" tabindex="-1"></a>  i16<span class="op">(</span><span class="dt">int16_t</span><span class="op">)</span>,</span>
<span id="cb79-10"><a href="#cb79-10" aria-hidden="true" tabindex="-1"></a>  u16<span class="op">(</span><span class="dt">uint16_t</span><span class="op">)</span>,</span>
<span id="cb79-11"><a href="#cb79-11" aria-hidden="true" tabindex="-1"></a>  i32<span class="op">(</span><span class="dt">int32_t</span><span class="op">)</span>,</span>
<span id="cb79-12"><a href="#cb79-12" aria-hidden="true" tabindex="-1"></a>  u32<span class="op">(</span><span class="dt">uint32_t</span><span class="op">)</span>,</span>
<span id="cb79-13"><a href="#cb79-13" aria-hidden="true" tabindex="-1"></a>  i64<span class="op">(</span><span class="dt">int64_t</span><span class="op">)</span>,</span>
<span id="cb79-14"><a href="#cb79-14" aria-hidden="true" tabindex="-1"></a>  u64<span class="op">(</span><span class="dt">uint64_t</span><span class="op">)</span>,</span>
<span id="cb79-15"><a href="#cb79-15" aria-hidden="true" tabindex="-1"></a>  s<span class="op">(</span>string<span class="op">)</span>;</span>
<span id="cb79-16"><a href="#cb79-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb79-17"><a href="#cb79-17" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> is_signed<span class="op">(</span><span class="kw">const</span> self<span class="op">^)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb79-18"><a href="#cb79-18" aria-hidden="true" tabindex="-1"></a>    <span class="co">// concise form. Equivalent to Rust&#39;s matches! macro.</span></span>
<span id="cb79-19"><a href="#cb79-19" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> match<span class="op">(*</span>self; <span class="op">.</span>i8 <span class="op">|</span> <span class="op">.</span>i16 <span class="op">|</span> <span class="op">.</span>i32 <span class="op">|</span> <span class="op">.</span>i64<span class="op">)</span>;</span>
<span id="cb79-20"><a href="#cb79-20" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb79-21"><a href="#cb79-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb79-22"><a href="#cb79-22" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> is_unsigned<span class="op">(</span><span class="kw">const</span> self<span class="op">^)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb79-23"><a href="#cb79-23" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> match<span class="op">(*</span>self; <span class="op">.</span>u8 <span class="op">|</span> <span class="op">.</span>u16 <span class="op">|</span> <span class="op">.</span>u32 <span class="op">|</span> <span class="op">.</span>u64<span class="op">)</span>;</span>
<span id="cb79-24"><a href="#cb79-24" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb79-25"><a href="#cb79-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb79-26"><a href="#cb79-26" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> is_string<span class="op">(</span><span class="kw">const</span> self<span class="op">^)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb79-27"><a href="#cb79-27" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> match<span class="op">(*</span>self; <span class="op">.</span>s<span class="op">)</span>;</span>
<span id="cb79-28"><a href="#cb79-28" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb79-29"><a href="#cb79-29" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb79-30"><a href="#cb79-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb79-31"><a href="#cb79-31" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb79-32"><a href="#cb79-32" aria-hidden="true" tabindex="-1"></a>  println<span class="op">(</span>Primitive<span class="op">::</span>i16<span class="op">(</span><span class="dv">5</span><span class="bu">i</span><span class="er">16</span><span class="op">).</span>is_signed<span class="op">())</span>;</span>
<span id="cb79-33"><a href="#cb79-33" aria-hidden="true" tabindex="-1"></a>  println<span class="op">(</span>Primitive<span class="op">::</span>u32<span class="op">(</span><span class="dv">100</span><span class="bu">u</span><span class="er">i32</span><span class="op">).</span>is_unsigned<span class="op">())</span>;</span>
<span id="cb79-34"><a href="#cb79-34" aria-hidden="true" tabindex="-1"></a>  println<span class="op">(</span>Primitive<span class="op">::</span>s<span class="op">(</span><span class="st">&quot;Hello safety&quot;</span><span class="op">).</span>is_string<span class="op">())</span>;</span>
<span id="cb79-35"><a href="#cb79-35" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The <em>concise-match-expression</em> is an abbreviated syntax for
pattern matching that evaluates a pattern and a <em>match-guard</em>.
This maps directly to Rust’s <span class="citation" data-cites="matches">[<a href="https://doc.rust-lang.org/std/macro.matches.html" role="doc-biblioref">matches</a>]</span> facility, although instead of
being a macro, this is a first-class language feature.</p>
<p>We’re working on better specifying the binding modes for match
declarations and their interactions with the relocation object model and
with the borrow checker. We hope to show more complex usage for the next
revision.</p>
<h2 data-number="2.6" id="interior-mutability"><span class="header-section-number">2.6</span> Interior mutability<a href="#interior-mutability" class="self-link"></a></h2>
<p>Recall the law of exclusivity, the program-wide invariant that
guarantees a resource isn’t mutated while another user aliases it. How
does this square with the use of shared pointers, which enables shared
ownership of a mutable resource? How does it support threaded programs,
where access to shared mutable state is permitted between threads?
Shared mutable access exists in this safety model, but the way it’s
enabled involves some trickery.</p>
<div class="sourceCode" id="cb80"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb80-1"><a href="#cb80-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">+&gt;</span></span>
<span id="cb80-2"><a href="#cb80-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="op">[[</span><span class="at">unsafe</span><span class="op">::</span><span class="at">sync</span><span class="op">(</span><span class="at">false</span><span class="op">)]]</span> unsafe_cell</span>
<span id="cb80-3"><a href="#cb80-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb80-4"><a href="#cb80-4" aria-hidden="true" tabindex="-1"></a>  T t_;</span>
<span id="cb80-5"><a href="#cb80-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb80-6"><a href="#cb80-6" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb80-7"><a href="#cb80-7" aria-hidden="true" tabindex="-1"></a>  unsafe_cell<span class="op">()</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb80-8"><a href="#cb80-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb80-9"><a href="#cb80-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">explicit</span></span>
<span id="cb80-10"><a href="#cb80-10" aria-hidden="true" tabindex="-1"></a>  unsafe_cell<span class="op">(</span>T t<span class="op">)</span> <span class="kw">noexcept</span> safe</span>
<span id="cb80-11"><a href="#cb80-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> t_<span class="op">(</span>rel t<span class="op">)</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb80-12"><a href="#cb80-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb80-13"><a href="#cb80-13" aria-hidden="true" tabindex="-1"></a>  T<span class="op">*</span> get<span class="op">(</span>self <span class="kw">const</span><span class="op">^)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb80-14"><a href="#cb80-14" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="kw">const_cast</span><span class="op">&lt;</span>T<span class="op">*&gt;(</span>addr self<span class="op">-&gt;</span>t_<span class="op">)</span>;</span>
<span id="cb80-15"><a href="#cb80-15" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb80-16"><a href="#cb80-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>Types with interior mutability implement <em>deconfliction</em>
strategies to support shared mutation without the risk of data races or
violating exclusivity. They encapsulate <code class="sourceCode cpp">std2<span class="op">::</span>unsafe_cell</code>,
which is based on Rust’s
<code class="sourceCode cpp">UnsafeCell</code><span class="citation" data-cites="unsafe-cell">[<a href="https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html" role="doc-biblioref">unsafe-cell</a>]</span> struct. <code class="sourceCode cpp">unsafe_cell<span class="op">::</span>get</code>
is a blessed way of stripping away const. While the function is safe, it
returns a raw pointer, which is unsafe to dereference. Types
encapsulating <code class="sourceCode cpp">unsafe_cell</code> must take
care to only permit mutation through this const-stripped pointer one
user at a time.</p>
<p>Our safe standard library currently offers four types with interior
mutability:</p>
<ul>
<li><code class="sourceCode cpp">std2<span class="op">::</span>cell<span class="op">&lt;</span>T<span class="op">&gt;</span></code><span class="citation" data-cites="cell">[<a href="https://doc.rust-lang.org/std/cell/struct.Cell.html" role="doc-biblioref">cell</a>]</span> provides get and set methods to
read out the current value and store new values into the protected
resource. Since <code class="sourceCode cpp">cell</code> can’t be used
across threads, there’s no risk of violating exclusivity.</li>
<li><code class="sourceCode cpp">std2<span class="op">::</span>ref_cell<span class="op">&lt;</span>T<span class="op">&gt;</span></code><span class="citation" data-cites="ref-cell">[<a href="https://doc.rust-lang.org/std/cell/struct.RefCell.html" role="doc-biblioref">ref-cell</a>]</span> is a single-threaded
multiple-read, single-write lock. If the caller requests a mutable
reference to the interior object, the implementation checks its counter,
and if the object is not locked, it establishes a mutable lock and
returns a mutable borrow. If the caller requests a shared reference to
the interior object, the implementation checks that there is no live
mutable borrow, and if there isn’t, increments the counter. When users
are done with the borrow, they have to release the lock, which
decrements the reference count. If the user’s request can’t be serviced,
the <code class="sourceCode cpp">ref_cell</code> can either gracefully
return with an error code, or it can panic and abort.</li>
<li><code class="sourceCode cpp">std2<span class="op">::</span>mutex<span class="op">&lt;</span>T<span class="op">&gt;</span></code><span class="citation" data-cites="mutex">[<a href="https://doc.rust-lang.org/std/sync/struct.Mutex.html" role="doc-biblioref">mutex</a>]</span> provides mutable borrows to the
interior data across threads. A mutex synchronization object deconflicts
access, so there’s only one live borrow at a time.</li>
<li><code class="sourceCode cpp">std2<span class="op">::</span>shared_mutex<span class="op">&lt;</span>T<span class="op">&gt;</span></code><span class="citation" data-cites="rwlock">[<a href="https://doc.rust-lang.org/std/sync/struct.RwLock.html" role="doc-biblioref">rwlock</a>]</span> is the threaded multiple-read,
single-write lock. The interface is similar to
<code class="sourceCode cpp">ref_cell</code>’s, but it uses a mutex for
deconfliction, so clients can sit on the lock until their request is
serviced.</li>
</ul>
<div class="sourceCode" id="cb81"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb81-1"><a href="#cb81-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">+&gt;</span></span>
<span id="cb81-2"><a href="#cb81-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span></span>
<span id="cb81-3"><a href="#cb81-3" aria-hidden="true" tabindex="-1"></a><span class="op">[[</span><span class="at">unsafe</span><span class="op">::</span><span class="at">send</span><span class="op">(</span><span class="at">T</span><span class="op">~</span><span class="at">is_send</span><span class="op">)</span>,<span class="at"> unsafe</span><span class="op">::</span><span class="at">sync</span><span class="op">(</span><span class="at">T</span><span class="op">~</span><span class="at">is_send</span><span class="op">)]]</span></span>
<span id="cb81-4"><a href="#cb81-4" aria-hidden="true" tabindex="-1"></a>mutex</span>
<span id="cb81-5"><a href="#cb81-5" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb81-6"><a href="#cb81-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> mutex_type <span class="op">=</span> unsafe_cell<span class="op">&lt;</span>std<span class="op">::</span>mutex<span class="op">&gt;</span>;</span>
<span id="cb81-7"><a href="#cb81-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb81-8"><a href="#cb81-8" aria-hidden="true" tabindex="-1"></a>  unsafe_cell<span class="op">&lt;</span>T<span class="op">&gt;</span> data_;</span>
<span id="cb81-9"><a href="#cb81-9" aria-hidden="true" tabindex="-1"></a>  box<span class="op">&lt;</span>mutex_type<span class="op">&gt;</span> mtx_;</span>
<span id="cb81-10"><a href="#cb81-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb81-11"><a href="#cb81-11" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb81-12"><a href="#cb81-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">class</span> lock_guard<span class="op">/(</span>a<span class="op">)</span></span>
<span id="cb81-13"><a href="#cb81-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb81-14"><a href="#cb81-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">class</span> mutex;</span>
<span id="cb81-15"><a href="#cb81-15" aria-hidden="true" tabindex="-1"></a>    mutex <span class="kw">const</span><span class="op">^/</span>a m_;</span>
<span id="cb81-16"><a href="#cb81-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb81-17"><a href="#cb81-17" aria-hidden="true" tabindex="-1"></a>    lock_guard<span class="op">(</span>mutex <span class="kw">const</span><span class="op">^/</span>a m<span class="op">)</span> <span class="kw">noexcept</span> safe</span>
<span id="cb81-18"><a href="#cb81-18" aria-hidden="true" tabindex="-1"></a>      <span class="op">:</span> m_<span class="op">(</span>m<span class="op">)</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb81-19"><a href="#cb81-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb81-20"><a href="#cb81-20" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span><span class="op">:</span></span>
<span id="cb81-21"><a href="#cb81-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">~</span>lock_guard<span class="op">()</span> safe <span class="op">{</span></span>
<span id="cb81-22"><a href="#cb81-22" aria-hidden="true" tabindex="-1"></a>      unsafe <span class="op">{</span> mut m_<span class="op">-&gt;</span>mtx_<span class="op">-&gt;</span>get<span class="op">()-&gt;</span>unlock<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb81-23"><a href="#cb81-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb81-24"><a href="#cb81-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb81-25"><a href="#cb81-25" aria-hidden="true" tabindex="-1"></a>    T<span class="op">^</span> borrow<span class="op">(</span>self<span class="op">^)</span> <span class="kw">noexcept</span> safe <span class="op">{</span></span>
<span id="cb81-26"><a href="#cb81-26" aria-hidden="true" tabindex="-1"></a>      unsafe <span class="op">{</span> <span class="cf">return</span> <span class="op">^*</span>self<span class="op">-&gt;</span>m_<span class="op">-&gt;</span>data_<span class="op">.</span>get<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb81-27"><a href="#cb81-27" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb81-28"><a href="#cb81-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb81-29"><a href="#cb81-29" aria-hidden="true" tabindex="-1"></a>    <span class="op">...</span></span>
<span id="cb81-30"><a href="#cb81-30" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb81-31"><a href="#cb81-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb81-32"><a href="#cb81-32" aria-hidden="true" tabindex="-1"></a>  <span class="kw">explicit</span> mutex<span class="op">(</span>T data<span class="op">)</span> <span class="kw">noexcept</span> safe</span>
<span id="cb81-33"><a href="#cb81-33" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> data_<span class="op">(</span>rel data<span class="op">)</span></span>
<span id="cb81-34"><a href="#cb81-34" aria-hidden="true" tabindex="-1"></a>    , unsafe mtx_<span class="op">(</span>box<span class="op">&lt;</span>mutex_type<span class="op">&gt;::</span>make<span class="op">())</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb81-35"><a href="#cb81-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb81-36"><a href="#cb81-36" aria-hidden="true" tabindex="-1"></a>  mutex<span class="op">(</span>mutex <span class="kw">const</span><span class="op">^)</span> <span class="op">=</span> <span class="kw">delete</span>;</span>
<span id="cb81-37"><a href="#cb81-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb81-38"><a href="#cb81-38" aria-hidden="true" tabindex="-1"></a>  lock_guard lock<span class="op">(</span>self <span class="kw">const</span><span class="op">^)</span> safe <span class="op">{</span></span>
<span id="cb81-39"><a href="#cb81-39" aria-hidden="true" tabindex="-1"></a>    unsafe <span class="op">{</span> mut self<span class="op">-&gt;</span>mtx_<span class="op">-&gt;</span>get<span class="op">()-&gt;</span>lock<span class="op">()</span>;<span class="op">}</span></span>
<span id="cb81-40"><a href="#cb81-40" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> lock_guard<span class="op">(</span>self<span class="op">)</span>;</span>
<span id="cb81-41"><a href="#cb81-41" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb81-42"><a href="#cb81-42" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<div class="sourceCode" id="cb82"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb82-1"><a href="#cb82-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> entry_point<span class="op">(</span>arc<span class="op">&lt;</span>mutex<span class="op">&lt;</span>string<span class="op">&gt;&gt;</span> data, <span class="dt">int</span> thread_id<span class="op">)</span> safe <span class="op">{</span></span>
<span id="cb82-2"><a href="#cb82-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> lock_guard <span class="op">=</span> data<span class="op">-&gt;</span>lock<span class="op">()</span>;</span>
<span id="cb82-3"><a href="#cb82-3" aria-hidden="true" tabindex="-1"></a>  string<span class="op">^</span> s <span class="op">=</span> mut lock_guard<span class="op">.</span>borrow<span class="op">()</span>;</span>
<span id="cb82-4"><a href="#cb82-4" aria-hidden="true" tabindex="-1"></a>  s<span class="op">.</span>append<span class="op">(</span><span class="st">&quot;🔥&quot;</span><span class="op">)</span>;</span>
<span id="cb82-5"><a href="#cb82-5" aria-hidden="true" tabindex="-1"></a>  println<span class="op">(*</span>s<span class="op">)</span>;</span>
<span id="cb82-6"><a href="#cb82-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Let’s examine how
<code class="sourceCode cpp">std2<span class="op">::</span>mutex</code>
implements interior mutability to obey the law of exclusivity while
permitting mutation through const borrows. We’ve stripped the comments
from the example in the <a href="#thread-safety">thread safety</a>
section. <code class="sourceCode cpp">data</code> is an
<code class="sourceCode cpp">arc</code> and
<code class="sourceCode cpp">data<span class="op">-&gt;</span></code>
returns a <code class="sourceCode cpp"><span class="kw">const</span> mutex<span class="op">&lt;</span>string<span class="op">&gt;^</span></code>.
Normally this is immutable. But <code class="sourceCode cpp">std2<span class="op">::</span>mutex<span class="op">::</span>lock</code>
binds a const <code class="sourceCode cpp">self</code>. Its
<code class="sourceCode cpp">mtx_</code> data member has type <code class="sourceCode cpp">box<span class="op">&lt;</span>unsafe_cell<span class="op">&lt;</span>std<span class="op">::</span>mutex<span class="op">&gt;&gt;</span></code>.
<code class="sourceCode cpp">std<span class="op">::</span>mutex</code>
is non-movable, so we’re hosting it in a box on the heap to make
<code class="sourceCode cpp">std2<span class="op">::</span>mutex</code>
movable.
<code class="sourceCode cpp">mut_<span class="op">-&gt;</span></code>
returns <code class="sourceCode cpp"><span class="kw">const</span> unsafe_cell<span class="op">&lt;</span>std<span class="op">::</span>mutex<span class="op">&gt;^</span></code>
because the <code class="sourceCode cpp">self</code> reference is const.
But <code class="sourceCode cpp">mut_<span class="op">-&gt;</span>get<span class="op">()</span></code>
returns <code class="sourceCode cpp">std<span class="op">::</span>mutex<span class="op">*</span></code>!
The const was stripped off by <code class="sourceCode cpp">unsafe_cell<span class="op">::</span>get</code>.
This is the pivot in interior mutability that allows the system to work.
We have mutable pointer to
<code class="sourceCode cpp">std<span class="op">::</span>mutex</code>
and simply lock it.</p>
<p>The <code class="sourceCode cpp">lock_guard</code> is a view into the
<code class="sourceCode cpp">std2<span class="op">::</span>mutex</code>
with a named lifetime parameter. When the
<code class="sourceCode cpp">lock_guard</code> goes out of scope, it
calls <code class="sourceCode cpp">unlock</code> on the system mutex.
The guard’s lifetime parameter
<code class="sourceCode cpp"><span class="op">/</span>a</code> keeps the
mutex in scope as long as the
<code class="sourceCode cpp">lock_guard</code> is in scope, or the
borrow checker errors.</p>
<p>Lifetime safety also guarantees that the
<code class="sourceCode cpp">lock_guard</code> is in scope (meaning the
mutex is locked) whenever the reference into the protected resource is
used. <code class="sourceCode cpp">lock_guard<span class="op">::</span>borrow</code>
connects the lifetime on the return borrow
<code class="sourceCode cpp">T<span class="op">^</span></code> with the
lifetime on self. If the lock guard goes out of scope while the returned
borrow is live, that’s a borrow checker error.</p>
<p>Interior mutability is a legal loophole around exclusivity. You’re
still limited to one mutable borrow or any number of shared borrows to
an object. Types with a deconfliction strategy use
<code class="sourceCode cpp">unsafe_cell</code> to safely strip the
const off shared borrows, allowing users to mutate the protected
resource.</p>
<p>Safe C++ and Rust and conflate exclusive access with mutable borrows
and shared access with const borrows. It’s is an economical choice,
because one type qualifier,
<code class="sourceCode cpp"><span class="kw">const</span></code> or
<code class="sourceCode cpp">mut</code>, also determines exclusivity.
But the cast-away-const model of interior mutability is an awkward
consequence. But this design is not the only way: The Ante language<span class="citation" data-cites="ante">[<a href="https://antelang.org/blog/safe_shared_mutability/#shared-interior-mutability" role="doc-biblioref">ante</a>]</span> experiments with separate
<code class="sourceCode cpp">own mut</code> and
<code class="sourceCode cpp">shared mut</code> qualifiers. That’s really
attractive, because you’re never mutating something through a const
reference. This three-state system doesn’t map onto C++’s existing type
system as easily, but that doesn’t mean the const/mutable borrow
treatment, which does integrate elegantly, is the most expressive. A
<code class="sourceCode cpp">shared</code> type qualifier merits
investigation during the course of this project.</p>
<ul>
<li><code class="sourceCode cpp">T<span class="op">^</span></code> -
Exclusive mutable access. Permits standard conversion to
<code class="sourceCode cpp">shared T<span class="op">^</span></code>
and <code class="sourceCode cpp"><span class="kw">const</span> T<span class="op">^</span></code>.</li>
<li><code class="sourceCode cpp">shared T<span class="op">^</span></code>
- Shared mutable access. Permits standard conversion to <code class="sourceCode cpp"><span class="kw">const</span> T<span class="op">^</span></code>.
Only types that enforce interior mutability have overloads with shared
mutable access.</li>
<li><code class="sourceCode cpp"><span class="kw">const</span> T<span class="op">^</span></code>
- Shared constant access.</li>
</ul>
<h2 data-number="2.7" id="send-and-sync"><span class="header-section-number">2.7</span>
<code class="sourceCode cpp">send</code> and
<code class="sourceCode cpp">sync</code><a href="#send-and-sync" class="self-link"></a></h2>
<p>Thread safety is perhaps the most remarkable guarantee made by Rust’s
memory safety model. Central to its implementation are the
<code class="sourceCode cpp">send</code> and
<code class="sourceCode cpp">sync</code> traits:</p>
<blockquote>
<p>Some types allow you to have multiple aliases of a location in memory
while mutating it. Unless these types use synchronization to manage this
access, they are absolutely not thread-safe. Rust captures this through
the Send and Sync traits.</p>
<ul>
<li>A type is Send if it is safe to send it to another thread.<br />
</li>
<li>A type is Sync if it is safe to share between threads (T is Sync if
and only if &amp;T is Send).</li>
</ul>
<p>– Rustnomicon<span class="citation" data-cites="send-sync">[<a href="https://doc.rust-lang.org/nomicon/send-and-sync.html" role="doc-biblioref">send-sync</a>]</span></p>
</blockquote>
<p>Safe C++ follows this model and implements
<code class="sourceCode cpp">std2<span class="op">::</span>send</code>
and
<code class="sourceCode cpp">std2<span class="op">::</span>sync</code>
as interfaces. Specify the interface values for a type using the <code class="sourceCode cpp"><span class="op">[[</span><span class="at">unsafe</span><span class="op">::</span><span class="at">send</span><span class="op">]]</span></code>
and <code class="sourceCode cpp"><span class="op">[[</span><span class="at">unsafe</span><span class="op">::</span><span class="at">sync</span><span class="op">]]</span></code>
attributes. Query the interface values with the
<code class="sourceCode cpp">T<span class="op">~</span>is_send</code>
and
<code class="sourceCode cpp">T<span class="op">~</span>is_sync</code>
member traits.</p>
<div class="sourceCode" id="cb83"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb83-1"><a href="#cb83-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">+&gt;</span></span>
<span id="cb83-2"><a href="#cb83-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="op">[[</span><span class="at">unsafe</span><span class="op">::</span><span class="at">send</span><span class="op">(</span><span class="at">false</span><span class="op">)]]</span> rc;</span></code></pre></div>
<p><code class="sourceCode cpp">std2<span class="op">::</span>rc</code>
is the non-atomic reference-counted pointer. It permits shared ownership
but only within a single thread. Its declaration marks it <code class="sourceCode cpp">send<span class="op">(</span><span class="kw">false</span><span class="op">)</span></code>.
It can’t be copied to other threads, since the non-atomic reference
counter would cause data races.</p>
<div class="sourceCode" id="cb84"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb84-1"><a href="#cb84-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">+&gt;</span></span>
<span id="cb84-2"><a href="#cb84-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="op">[[</span></span>
<span id="cb84-3"><a href="#cb84-3" aria-hidden="true" tabindex="-1"></a><span class="at">  unsafe</span><span class="op">::</span><span class="at">send</span><span class="op">(</span><span class="at">T</span><span class="op">~</span><span class="at">is_send </span><span class="op">&amp;&amp;</span><span class="at"> T</span><span class="op">~</span><span class="at">is_sync</span><span class="op">)</span>,</span>
<span id="cb84-4"><a href="#cb84-4" aria-hidden="true" tabindex="-1"></a><span class="at">  unsafe</span><span class="op">::</span><span class="at">sync</span><span class="op">(</span><span class="at">T</span><span class="op">~</span><span class="at">is_send </span><span class="op">&amp;&amp;</span><span class="at"> T</span><span class="op">~</span><span class="at">is_sync</span><span class="op">)</span></span>
<span id="cb84-5"><a href="#cb84-5" aria-hidden="true" tabindex="-1"></a><span class="op">]]</span> arc;</span></code></pre></div>
<p><code class="sourceCode cpp">std2<span class="op">::</span>arc</code>
is the atomic reference-counted pointer. If its inner type is both
<code class="sourceCode cpp">send</code> and
<code class="sourceCode cpp">sync</code>, then the
<code class="sourceCode cpp">arc</code> specialization is also
<code class="sourceCode cpp">send</code> and
<code class="sourceCode cpp">sync</code>. Most types with <em>value
semantics</em>, including builtin types, are
<code class="sourceCode cpp">send</code> and
<code class="sourceCode cpp">sync</code>. By the rules of <em>inherited
mutability</em>, so are aggregate types built from
<code class="sourceCode cpp">send</code> and
<code class="sourceCode cpp">sync</code> subobjects. <code class="sourceCode cpp">std2<span class="op">::</span>arc<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span></code>
is <code class="sourceCode cpp">send</code>, permitting copy to other
threads.</p>
<p>But <code class="sourceCode cpp">std2;<span class="op">:</span>arc<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span></code>
isn’t an interesting case. <code class="sourceCode cpp">arc</code>’s
interface only produces <em>const</em> borrows to the owned value: you
can’t have a data race if you’re only reading from something.
<code class="sourceCode cpp">arc</code> is intended to be used with
types that implement <a href="#interior-mutability"><em>interior
mutability</em></a>, permitting mutation through const references.
<code class="sourceCode cpp">sync</code> characterizes the thread safety
of hde deconfliction mechanisms of types with interior mutability. Is
that deconfliction mechanism <em>single threaded</em>
(<code class="sourceCode cpp">sync</code>=false) or
<em>multi-threaded</em>
(<code class="sourceCode cpp">sync</code>=true)?</p>
<div class="sourceCode" id="cb85"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb85-1"><a href="#cb85-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">+&gt;</span></span>
<span id="cb85-2"><a href="#cb85-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="op">[[</span><span class="at">unsafe</span><span class="op">::</span><span class="at">sync</span><span class="op">(</span><span class="at">false</span><span class="op">)]]</span> cell;</span></code></pre></div>
<p><code class="sourceCode cpp">std2<span class="op">::</span>cell</code>
implements interior mutability, making it a candidate for use with
<code class="sourceCode cpp">std2<span class="op">::</span>arc</code>.
It uses <em>transactions</em> for deconfliction: callers may only
<code class="sourceCode cpp">set</code> or
<code class="sourceCode cpp">get</code> the interior value. This system
is robust within a thread, but unsound across threads: thread 1 could
<code class="sourceCode cpp">set</code> a value while thread 2
<code class="sourceCode cpp">get</code>s it, producing a data race.
<code class="sourceCode cpp">std2<span class="op">::</span>cell</code>
is marked <code class="sourceCode cpp">sync<span class="op">(</span><span class="kw">false</span><span class="op">)</span></code>:
it’s unsafe to share borrows to a
<code class="sourceCode cpp">cell</code> across threads due to risk of
data race.</p>
<div class="sourceCode" id="cb86"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb86-1"><a href="#cb86-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">+&gt;</span></span>
<span id="cb86-2"><a href="#cb86-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="op">[[</span></span>
<span id="cb86-3"><a href="#cb86-3" aria-hidden="true" tabindex="-1"></a><span class="at">  unsafe</span><span class="op">::</span><span class="at">send</span><span class="op">(</span><span class="at">T</span><span class="op">~</span><span class="at">is_send</span><span class="op">)</span>,</span>
<span id="cb86-4"><a href="#cb86-4" aria-hidden="true" tabindex="-1"></a><span class="at">  unsafe</span><span class="op">::</span><span class="at">sync</span><span class="op">(</span><span class="at">T</span><span class="op">~</span><span class="at">is_send</span><span class="op">)</span></span>
<span id="cb86-5"><a href="#cb86-5" aria-hidden="true" tabindex="-1"></a><span class="op">]]</span> mutex;</span></code></pre></div>
<p><code class="sourceCode cpp">std2<span class="op">::</span>mutex</code>
is another candidate for use with
<code class="sourceCode cpp">std2<span class="op">::</span>arc</code>.
This type is thread safe. As shown in the <a href="#thread-safety">thread safety</a> example, it provides threads
with exclusive access to its interior data using a synchronization
object. The borrow checker prevents the reference to the inner data from
being used outside of the mutex’s lock. Therefore,
<code class="sourceCode cpp">std2<span class="op">::</span>mutex</code>
is <code class="sourceCode cpp">sync</code> if its inner type is
<code class="sourceCode cpp">send</code>. Why make it conditional on
<code class="sourceCode cpp">send</code> when the mutex is already
providing threads with exclusive access to the inner value? This
provides protection for the rare type with thread affinity. A type is
<code class="sourceCode cpp">send</code> if it can both be copied to a
different thread <em>and used</em> by a different thread.</p>
<p><code class="sourceCode cpp">std2<span class="op">::</span>arc<span class="op">&lt;</span>std2<span class="op">::</span>mutex<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span></code>
is <code class="sourceCode cpp">send</code> if <code class="sourceCode cpp">std2<span class="op">::</span>mutex<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
is <code class="sourceCode cpp">send</code> and
<code class="sourceCode cpp">sync</code>. <code class="sourceCode cpp">std2<span class="op">::</span>mutex<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
is <code class="sourceCode cpp">send</code> and
<code class="sourceCode cpp">sync</code> if
<code class="sourceCode cpp">T</code> is
<code class="sourceCode cpp">send</code>. Since most types are
<code class="sourceCode cpp">send</code> by construction, we can safely
mutate shared state over multiple threads as long as its wrapped in a
<code class="sourceCode cpp">std2<span class="op">::</span>mutex</code>
and that’s owned by an
<code class="sourceCode cpp">std2<span class="op">::</span>arc</code>.
The <code class="sourceCode cpp">arc</code> provides shared ownership.
The <code class="sourceCode cpp">mutex</code> provides shared
mutation.</p>
<div class="sourceCode" id="cb87"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb87-1"><a href="#cb87-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> thread <span class="op">{</span></span>
<span id="cb87-2"><a href="#cb87-2" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb87-3"><a href="#cb87-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> F<span class="op">+</span>, <span class="kw">class</span> <span class="op">...</span>Args<span class="op">+&gt;</span></span>
<span id="cb87-4"><a href="#cb87-4" aria-hidden="true" tabindex="-1"></a>  thread<span class="op">/(</span>where F<span class="op">:</span> <span class="kw">static</span>, Args<span class="op">...:</span> <span class="kw">static</span><span class="op">)(</span>F f, Args<span class="op">...</span> args<span class="op">)</span> safe</span>
<span id="cb87-5"><a href="#cb87-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span><span class="op">(</span></span>
<span id="cb87-6"><a href="#cb87-6" aria-hidden="true" tabindex="-1"></a>    F<span class="op">~</span>is_send <span class="op">&amp;&amp;</span></span>
<span id="cb87-7"><a href="#cb87-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">(</span>Args<span class="op">~</span>is_send <span class="op">&amp;&amp;</span> <span class="op">...)</span> <span class="op">&amp;&amp;</span></span>
<span id="cb87-8"><a href="#cb87-8" aria-hidden="true" tabindex="-1"></a>    safe<span class="op">(</span>mut f<span class="op">(</span>rel args<span class="op">...)))</span></span>
<span id="cb87-9"><a href="#cb87-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> unsafe t_<span class="op">()</span></span>
<span id="cb87-10"><a href="#cb87-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb87-11"><a href="#cb87-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span>
<span id="cb87-12"><a href="#cb87-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>The <code class="sourceCode cpp">send</code> property is enforced by
<code class="sourceCode cpp">std2<span class="op">::</span>thread</code>’s
constructor. If all the thread arguments are
<code class="sourceCode cpp">send</code>, the <em>requires-clause</em>
evaluates true and the constructor may be called. If any argument is
<code class="sourceCode cpp">send</code>=false, the program is
ill-formed. Data races are a runtime phenomenon, but our protection is
guaranteed at compile time.</p>
<p>The <code class="sourceCode cpp">send</code> constraint against
demonstrates the safety model’s <a href="#memory-safety-as-terms-and-conditions">theme of
responsibility</a>: a <code class="sourceCode cpp">safe</code> function
must be sound for all arguments. Before entering an
<em>unsafe-block</em> and calling the unsafe system-level thread
function, <code class="sourceCode cpp">thread</code>’s constructor must
confirm that it’s enforcing the safety guarantees of its contract. Only
types that are <code class="sourceCode cpp">send</code> may be used
across threads.</p>
<p><code class="sourceCode cpp">std2<span class="op">::</span>thread</code>
is designed defensively with the safety promise that it won’t produce
undefined behavior no matter how it’s used. Can we fool
<code class="sourceCode cpp">thread</code> into producing a data
race?</p>
<p><strong>Pass a borrow to a value on the stack.</strong> There’s no
guarantee that the thread will join before the stack object is
destroyed. Is that a potential use-after-free? No, because the thread
has an <em>outlives-constraint</em> which checks that all function
arguments outlive <code class="sourceCode cpp"><span class="op">/</span><span class="kw">static</span></code>.
An <code class="sourceCode cpp">std2<span class="op">::</span>arc</code>
doesn’t have lifetime arguments (unless its inner type is a lifetime
binder), so that checks out. But a shared or mutable borrow does have a
lifetime argument, and if it refers to an object on the stack, it’s not
<code class="sourceCode cpp"><span class="op">/</span><span class="kw">static</span></code>.
Those are arguments are accepted by the <em>requires-clause</em> but are
rejected by the borrow checker.</p>
<p><strong>Pass a borrow to a global variable.</strong> If the global’s
type is not <code class="sourceCode cpp">sync</code>, then a borrow to
it is not <code class="sourceCode cpp">send</code>, and that’s a
constraint violation. If the global variable is mutable, that could
cause a data race. Fortunately it’s ill-formed to name mutable global
objects in a <a href="#the-safe-context">safe context</a>. Otherwise,
it’s safe to share const global objects between threads.</p>
<p>It’s the responsibility of a safe library to think through all
possible scenarios of use and prevent execution that could result in
soundness defects. After all, the library author is a specialist in that
domain. This is a friendlier system than Standard C++, which places the
all the weight of writing thread safe code on the shoulders of
users.</p>
<h2 data-number="2.8" id="unresolved-design-issues"><span class="header-section-number">2.8</span> Unresolved design issues<a href="#unresolved-design-issues" class="self-link"></a></h2>
<h3 data-number="2.8.1" id="expression-outlives-constraint"><span class="header-section-number">2.8.1</span>
<em>expression-outlives-constraint</em><a href="#expression-outlives-constraint" class="self-link"></a></h3>
<p>C++ variadics don’t convey lifetime constraints from a function’s
return type to its parameters. Calls like
<code class="sourceCode cpp">make_unique</code> and
<code class="sourceCode cpp">emplace_back</code> take parameters
<code class="sourceCode cpp">Ts<span class="op">...</span> args</code>
and return an unrelated type <code class="sourceCode cpp">T</code>. This
may trigger the borrow checker, because the implementation of the
function will produce free regions with unrelated endpoints. It’s not a
soundness issue, but it is a serious usability issue.</p>
<p>We need an <em>expression-outlives-constraint</em>, a programmatic
version of <em>outlives-constrant</em> <code class="sourceCode cpp"><span class="op">/(</span>where a <span class="op">:</span> b<span class="op">)</span></code>.
It would consist of an <em>expression</em> in an unevaluated context,
which names the actual function parameters and harvests the lifetime
constraints implied by those expressions. We should name function
parameters rather than declvals of their types, because they may be
borrow parameters with additional constraints than their template
lifetime parameters have.</p>
<p>In order to name the function parameters, we’ll need a trailing
<em>expression-lifetime-constraint</em> syntax. Something like,</p>
<div class="sourceCode" id="cb88"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb88-1"><a href="#cb88-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">+</span>, <span class="kw">typename</span><span class="op">...</span> Ts<span class="op">+&gt;</span></span>
<span id="cb88-2"><a href="#cb88-2" aria-hidden="true" tabindex="-1"></a>box<span class="op">&lt;</span>T<span class="op">&gt;</span> make_box<span class="op">(</span>Ts<span class="op">...</span> args<span class="op">)</span> safe where<span class="op">(</span>T<span class="op">:</span>T<span class="op">(</span>rel args<span class="op">...))</span>;</span></code></pre></div>
<p>There’s a unique tooling aspect to this. To evaluate the implied
constraints of the outlives expression, we have to lower the expression
to MIR, create new region variables for the locals, generate
constraints, solve the constraint equation, and propagate region end
points up to the function’s lifetime parameters.</p>
<h3 data-number="2.8.2" id="function-parameter-ownership"><span class="header-section-number">2.8.2</span> Function parameter
ownership<a href="#function-parameter-ownership" class="self-link"></a></h3>
<p>The C++ Standard does not specify parameter passing conventions.
That’s left to implementers. Unfortunately, different implementers
settled on different conventions.</p>
<blockquote>
<p>If the type has a non-trivial destructor, the caller calls that
destructor after control returns to it (including when the caller throws
an exception).</p>
<p>– <cite>Itanium C++ ABI: Non-Trivial Parameters</cite><span class="citation" data-cites="itanium-abi">[<a href="https://itanium-cxx-abi.github.io/cxx-abi/abi.html#non-trivial-parameters" role="doc-biblioref">itanium-abi</a>]</span></p>
</blockquote>
<p>In the Itanium C++ ABI, callers destruct function arguments after the
callee has returned. This isn’t compatible with Safe C++’s relocation
object model. If you relocate from a function parameter into a local
object, then the object would be destroyed <em>twice</em>: once by the
callee when the local object goes out of scope and once by the caller on
the call returns. Safe C++ specifies this aspect of parameter passing:
the callee is responsible for destroying its own function parameters. If
a function parameter is relocated out of, that parameter becomes
uninitialized and drop elaboration elides its destructor call.</p>
<p>Let’s say all functions declared in the <code class="sourceCode cpp"><span class="op">[</span>safety<span class="op">]</span></code>
feature implement the <em>relocate calling convention</em>. Direct calls
to them should be no problem. This includes virtual calls. Direct calls
to the legacy ABI from the relocate ABI should be no problem. And calls
going the other way, where the caller is in the legacy ABI and the
callee implements the relocate ABI, is not an issue either.</p>
<p>The friction comes when forming function pointers or
pointers-to-member functions for indirect calls. The pointer has to
contain ABI information in its type, and a pointer to a relocate ABI
function must have a different type than a pointer to the equivalent
legacy ABI function. Ideally we’d have an undecorated function pointer
type that can point to either legacy or relocate ABI functions, creating
a unified type for indirect function calls.</p>
<p>Consider these three new calling conventions:</p>
<ul>
<li><code class="sourceCode cpp">__relocate</code> - Relocate CC. Callee
destroys parameters. This is opt-in for both legacy and <code class="sourceCode cpp"><span class="op">[</span>safety<span class="op">]</span></code>
modes.</li>
<li><code class="sourceCode cpp">__legacy</code> - Legacy CC. The
system’s default calling convention. For Itanium ABI, the caller
destroys arguments.</li>
<li><code class="sourceCode cpp">__unified</code> - A unified CC that
holds function pointers of either the above types. The implementer can
use the most significant bit to store a discriminator between CCs:
set=<code class="sourceCode cpp">__relocate</code>,
cleared=<code class="sourceCode cpp">__legacy</code>. This is the
default for the <code class="sourceCode cpp"><span class="op">[</span>safety<span class="op">]</span></code>
mode.</li>
</ul>
<p>There’s a standard conversion from both
<code class="sourceCode cpp">__legacy</code> and
<code class="sourceCode cpp">__relocate</code> function pointers to the
<code class="sourceCode cpp">__unified</code> function pointer type. The
latter is a trivial bit-cast. The former merely demands setting the most
significant bit.</p>
<p>Surprisingly, we can also support standard conversions from a
<code class="sourceCode cpp">__unified</code> function pointer to the
<code class="sourceCode cpp">__legacy</code> and
<code class="sourceCode cpp">__relocate</code> function poiner types. If
it’s a mismatch, the null pointer is returned. This is still memory
safe, because dereferencing a pointer is the unsafe operation. However,
standard conversions from <code class="sourceCode cpp">__unified</code>
function references to <code class="sourceCode cpp">__legacy</code> and
<code class="sourceCode cpp">__relocate</code> references are not
supported, because references may not hold nullptr.</p>
<h3 data-number="2.8.3" id="non-static-member-functions-with-lifetimes"><span class="header-section-number">2.8.3</span> Non-static member functions
with lifetimes<a href="#non-static-member-functions-with-lifetimes" class="self-link"></a></h3>
<p>At this point in development, lifetime parameters are not supported
for non-static member functions where the enclosing class has lifetime
parameters, including including template lifetime parameters. Use the
<code class="sourceCode cpp">self</code> parameter to declare an
explicit object parameter. Non-static member functions don’t have full
object parameter types, which makes it challenging for the compiler to
attach lifetime arguments. As the project matures it’s likely that this
capability will be included.</p>
<p>Constructors, destructors and the relocation constructor don’t take
explicit <code class="sourceCode cpp">self</code> parameters. But that’s
less problematic because the language won’t form function pointers.</p>
<div class="sourceCode" id="cb89"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb89-1"><a href="#cb89-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Foo<span class="op">/</span>a <span class="op">{</span></span>
<span id="cb89-2"><a href="#cb89-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Self parameter syntax. Supported.</span></span>
<span id="cb89-3"><a href="#cb89-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> func1<span class="op">(</span>Foo<span class="op">^/</span>a self, <span class="dt">int</span> x<span class="op">)</span> safe;</span>
<span id="cb89-4"><a href="#cb89-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb89-5"><a href="#cb89-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Equivalent abbreviated self parameter syntax. Supported.</span></span>
<span id="cb89-6"><a href="#cb89-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> func2<span class="op">(</span>self<span class="op">^</span>, <span class="dt">int</span> x<span class="op">)</span> safe;</span>
<span id="cb89-7"><a href="#cb89-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb89-8"><a href="#cb89-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Possible non-static member function syntax.</span></span>
<span id="cb89-9"><a href="#cb89-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Bind a mutable borrow.</span></span>
<span id="cb89-10"><a href="#cb89-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> func3<span class="op">(</span><span class="dt">int</span> x<span class="op">)</span> <span class="op">^</span> safe;</span>
<span id="cb89-11"><a href="#cb89-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb89-12"><a href="#cb89-12" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Bind a shared borrow.</span></span>
<span id="cb89-13"><a href="#cb89-13" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> func4<span class="op">(</span><span class="dt">int</span> x<span class="op">)</span> <span class="kw">const</span><span class="op">^</span> safe;</span>
<span id="cb89-14"><a href="#cb89-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb89-15"><a href="#cb89-15" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Bind a consuming object. cv-qualifiers are unsupported.</span></span>
<span id="cb89-16"><a href="#cb89-16" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> func5<span class="op">(</span><span class="dt">int</span> x<span class="op">)</span> rel safe;</span>
<span id="cb89-17"><a href="#cb89-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>Supporting
<code class="sourceCode cpp"><span class="op">^</span></code> and
<code class="sourceCode cpp">rel</code> in the <em>ref-qualifier</em> on
a function declarator is a prospective syntax for supporting borrows and
relocation on the implicit object. However, inside the functions, you’d
still need to use the <code class="sourceCode cpp">self</code> keyword
rather than
<code class="sourceCode cpp"><span class="kw">this</span></code>,
because <code class="sourceCode cpp"><span class="kw">this</span></code>
produces pointers and it’s unsafe dereferencing pointers.</p>
<h3 data-number="2.8.4" id="relocation-out-of-references"><span class="header-section-number">2.8.4</span> Relocation out of
references<a href="#relocation-out-of-references" class="self-link"></a></h3>
<p>You can only relocate out of <em>owned places</em>, and owned places
are subobjects of local variables. Dereferences of borrows are not owned
places, so you can’t relocate out of them. Niko Matsakis writes about a
significant potential improvement in the ownership model, <span class="citation" data-cites="unwinding-puts-limits-on-the-borrow-checker">[<a href="https://smallcultfollowing.com/babysteps/blog/2024/05/02/unwind-considered-harmful/#unwinding-puts-limits-on-the-borrow-checker" role="doc-biblioref">unwinding-puts-limits-on-the-borrow-checker</a>]</span>
citing situations where it would be sound to relocate out of a
reference, as long as you relocate back into it before the function
returns.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> swap<span class="op">&lt;</span>T<span class="op">&gt;</span>(</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>    a<span class="op">:</span> <span class="op">&amp;</span><span class="kw">mut</span> T<span class="op">,</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>    b<span class="op">:</span> <span class="op">&amp;</span><span class="kw">mut</span> T<span class="op">,</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>) <span class="op">{</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> tmp <span class="op">=</span> <span class="op">*</span>a<span class="op">;</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">*</span>a <span class="op">=</span> <span class="op">*</span>b<span class="op">;</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">*</span>b <span class="op">=</span> tmp<span class="op">;</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The blog post considers the above swap function, which transliterates
to the Safe C++ code below.</p>
<div class="sourceCode" id="cb90"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb90-1"><a href="#cb90-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb90-2"><a href="#cb90-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> swap<span class="op">(</span>T<span class="op">^</span> a, T<span class="op">^</span> b<span class="op">)</span> safe <span class="op">{</span></span>
<span id="cb90-3"><a href="#cb90-3" aria-hidden="true" tabindex="-1"></a>  T tmp <span class="op">=</span> rel <span class="op">*</span>a;</span>
<span id="cb90-4"><a href="#cb90-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">*</span>a <span class="op">=</span> rel <span class="op">*</span>b;</span>
<span id="cb90-5"><a href="#cb90-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">*</span>b <span class="op">=</span> rel tmp;</span>
<span id="cb90-6"><a href="#cb90-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This code doesn’t compile under Rust or Safe C++ because the operand
of the relocation is a projection involving a reference, which is not an
<em>owned place</em>. This defeats the abilities of initialization
analysis.</p>
<p>In Rust, every function call is potentially throwing, including
destructors. In some builds, panics are throwing, allowing array
subscript operations to exit a function on the cleanup path. In debug
builds, integer arithmetic may panic to protect against overflow. There
are many non-return paths out functions, and unlike C++, Rust lacks a
<em>noexcept-specifier</em> to disable cleanup. Matsakis suggests that
relocating out of references is not implemented because its use would be
severely limited by the many unwind paths out of a function, making it
rather uneconomical to support.</p>
<p>It’s already possible to write C++ code that is less burdened by
cleanup paths than Rust. If Safe C++ adopted the <code class="sourceCode cpp"><span class="cf">throw</span><span class="op">()</span></code>
specifier from the Static Exception Specification,<span class="citation" data-cites="P3166R0">[<a href="https://wg21.link/p3166r0" role="doc-biblioref">P3166R0</a>]</span> we could statically verify that
functions don’t have internal cleanup paths. It may be worthwhile to
give
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>
interfaces to <code class="sourceCode cpp">vector</code> and similar
containers. Exceptions are a poor way to signal out-of-memory states. If
containers panicked on out-of-memory, we’d enormously reduce the cleanup
paths in most functions. Reducing cleanup paths extends the supported
interval between relocating out of a reference and restoring an object
there, helping justify the cost of more complex initialization
analysis.</p>
<p>This extended relocation feature is some of the ripest low-hanging
fruit for improving the safety experience in Safe C++.</p>
<h1 data-number="3" id="implementation-guidance"><span class="header-section-number">3</span> Implementation guidance<a href="#implementation-guidance" class="self-link"></a></h1>
<p>The intelligence behind the <em>ownership and borrowing</em> safety
model resides in the compiler’s middle-end, in its <em>MIR analysis</em>
passes. The first thing compiler engineers should focus on when pursuing
memory safety is to lower their frontend’s AST to MIR. Several compiled
languages already pass through a mid-level IR: Swift passes through
SIL,<span class="citation" data-cites="sil">[<a href="https://github.com/swiftlang/swift/blob/main/docs/SIL.rst" role="doc-biblioref">sil</a>]</span> Rust passes through MIR,<span class="citation" data-cites="mir">[<a href="https://rustc-dev-guide.rust-lang.org/mir/index.html" role="doc-biblioref">mir</a>]</span> and Circle passes through it’s
mid-level IR when targeting the new object model. There is an effort
called ClangIR<span class="citation" data-cites="clangir">[<a href="https://discourse.llvm.org/t/rfc-upstreaming-clangir/76587" role="doc-biblioref">clangir</a>]</span> to lower Clang to an MLIR
dialect called CIR, but the project is in an early phase and doesn’t
have enough coverage to support the language or library features
described in this document.</p>
<p>The AST-&gt;MIR and MIR-&gt;LLVM pipelines (or whatever codegen is
used) fully replaces the compiler’s old AST-&gt;LLVM codegen. It is more
difficult to lower through MIR than directly emitting LLVM, but
implementing new codegen is not a very large investment. You can look
into Circle’s MIR support with the <code class="sourceCode cpp"><span class="op">-</span>print<span class="op">-</span>mir</code>
and <code class="sourceCode cpp"><span class="op">-</span>print<span class="op">-</span>mir<span class="op">-</span>drop</code>
cmdline options, which print the MIR before and after drop elaboration,
respectively.</p>
<p>Once there is a MIR representation with adequete coverage, begin work
on the MIR analysis. Borrow checking is a very intricate algorithm, but
fortunately it’s easy to interrogate. Print the MIR and the lifetime and
outlives constraints as you lower and check functions to know where
you’re at. The NLL RFC<span class="citation" data-cites="borrow-checking">[<a href="https://rust-lang.github.io/rfcs/2094-nll.html" role="doc-biblioref">borrow-checking</a>]</span> is sufficient to get
developers started on MIR analysis. By my count there are seven rounds
of operations on MIR in the compiler’s middle-end:</p>
<ol type="1">
<li><strong>Initialization analysis</strong> - Perform forward dataflow
analysis on the control flow graph, finding all program points where a
place is initialized or uninitialized. This can be computed efficiently
with gen-kill analysis,<span class="citation" data-cites="gen-kill">[<a href="https://en.wikipedia.org/wiki/Data-flow_analysis#Bit_vector_problems" role="doc-biblioref">gen-kill</a>]</span> in which the gen and kill
states within a basic block are computed once and memoized into a pair
of bit vectors. An iterative fixed-point solver follows the control flow
graph and applies the gen-kill vectors to each basic block. After
establishing the initialization for each place, raise errors if any
uninitialized, partially initialized or potentially initialized place is
used.</li>
<li><strong>Live analysis</strong> - Invent new region variables for
each lifetime binder on each local variable in the function. Perform
reverse dataflow analysis on the control flow graph to find all program
points where a region is live or dead. A region is live when the borrow
it is bound to may be dereferenced at a subsequent point in the program.
This also has a gen-kill solution, but it’s computed in the opposite
direction.</li>
<li><strong>Variance analysis</strong> - Inter-procedural live analysis
solves the <em>constraint equation</em>. The constraints go one way:
<code class="sourceCode cpp"><span class="ch">&#39;R</span><span class="er">1 : </span><span class="ch">&#39;</span>R2 <span class="op">@</span> P3</code>
reads “R1 outlives R2 starting from the point P3.” Variance<span class="citation" data-cites="variance">[<a href="https://rust-lang.github.io/rfcs/0738-variance.html" role="doc-biblioref">variance</a>]</span> relates the lifetime
parameterizations of function parameters and return types to these
one-way constraints. It’s necessary to examine the definitions of
classes with lifetime binders and recursively examine their data member
types to solve for the variance<span class="citation" data-cites="taming-the-wildcards">[<a href="https://yanniss.github.io/variance-pldi11.pdf" role="doc-biblioref">taming-the-wildcards</a>]</span> for each function
call. Failure to appropriately solve for variance can result in
soundness holes, as illustrated by cve-rs<span class="citation" data-cites="cve-rs">[<a href="https://github.com/Speykious/cve-rs" role="doc-biblioref">cve-rs</a>]</span>, which drew attention to this
advanced aspect of the safety model.</li>
<li><strong>Type relation</strong> - Emit lifetime constraints to relate
assignments from one object with a region variable to another object
with a region variable. The variance of lifetime parameters determines
the directionality of lifetime constraints.</li>
<li><strong>Solve the constraint equation</strong> - Iteratively grow
region variables until all lifetime constraints emitted during type
relation are satisfied. We now have <em>inter-procedural live
analysis</em>: we know the full set of live borrows, <em>even through
function calls</em>.</li>
<li><strong>Borrow checking</strong> - Visit all instructions in the
control flow graph. For all <em>loans in scope</em> (i.e. the set of
loans live at each program point) test for invalidating actions.<span class="citation" data-cites="how-the-borrow-check-works">[<a href="https://rust-lang.github.io/rfcs/2094-nll.html#layer-5-how-the-borrow-check-works" role="doc-biblioref">how-the-borrow-check-works</a>]</span> If there’s a
read or write on an object with a mutable borrow in scope, or a write to
an object with a shared borrow in scope, that violates exclusivity, and
a borrowck errors is raised. The borrow checker also detects invalid end
points in free region variables.</li>
<li><strong>Drop elaboration</strong> - The relocation object model may
leave objects uninitialized, partially initialized or potentially
initialized at the point where they go out of scope. Drop elaboration
erases drops on uninitialized places, replaces drops on partially
initialized places with drops only on the initialized subobjects, and
gates drops on potentially initialized places behind drop flags. Drop
elaboration changes your program, and is the reason why MIR isn’t just
an analysis representation, but a transformation between the AST and the
code generator.</li>
</ol>
<p>This is challenging work for implementers. However, I found the
intelligibility of the MIR between every phase to be useful for making
steady progress.</p>
<p>The most demanding frontend work involves piping information from the
language syntax down to the MIR. Lifetime parameters on functions and
classes and necessitate a comprehensive change to the compiler’s type
system. Wherever there’s a type, you may now have a
<em>lifetime-qualified type</em>. (That is, a type with bound
lifetimes.)</p>
<p>Template specialization involves additional deduplication work, where
lifetime arguments on template argument types are replaced by proxy
lifetime arguments. This helps canonicalize specializations while
preserving the relationship established by its lifetime
parameterization. Lifetime normalization and canonicalization is also
very challenging to implement, partly because there is no precedent for
lifetime language entities in C++. In my experience this aspect of the
frontend work was the most frustrating and error-prone work I faced when
implementing memory safety. It suffers by comparison to the dataflow
analysis work, because it lacks that system’s elegant MIR
representation.</p>
<p>Implementing the <em>safe-specifier</em> and <em>safe-operator</em>
is easily achieved by duplicating the <em>noexcept</em> code paths.
These features are implemented in the frontend with similar means, and
their noexceptness/safeness are both conveyed through flags on
expressions.</p>
<p>Supporting the <code class="sourceCode cpp">unsafe</code> type
qualifier is more challenging, because the
<code class="sourceCode cpp"><span class="kw">const</span></code> and
<code class="sourceCode cpp"><span class="kw">volatile</span></code>
qualifiers offer less guidance. Unlike the cv-qualifiers, the unsafe
qualifier is ignored when examining pairs of types for ref-relation, but
is attached to prvalues that are the result of lvalue-to-rvalue
conversions, pointer adjustments, subobject access and the like.</p>
<p>There are some new syntax requirements. Circle chose the <code class="sourceCode cpp"><span class="pp">#</span><span class="er">feature</span></code>
directive to accommodate deep changes to the grammar and semantics of
the language with a per-file scope, rather than per-translation unit
scope. The directive is implemented by notionally including a mask of
active features for each token in the translation unit. During
tokenization, identifier tokens check their feature masks for the
[safety] feature, which enables promotion of the
<code class="sourceCode cpp">safe</code>,
<code class="sourceCode cpp">unsafe</code>,
<code class="sourceCode cpp">cpy</code>,
<code class="sourceCode cpp">rel</code>,
<code class="sourceCode cpp">match</code>,
<code class="sourceCode cpp">mut</code> tokens as keywords. The frontend
can simply match against these new keywords when parsing the input and
building the AST. Certain aspects of the relocation object model, such
as using drop-and-replace instead of invoking assignment operators,
don’t involve new keywords and are implemented by testing the object
model mode of the current function. The mode is established by the state
of the <code class="sourceCode cpp"><span class="op">[</span>safety<span class="op">]</span></code>
flag at the start of the function’s definition.</p>
<p>In addition to the core safety features, there are many new types
that put a demand on engineering resources: borrows, choice types and
pattern matching to use them, first-class tuples, arrays and slices.
Interfaces and interface templates are a new language mechanism that
provide customization points to C++, making it much easier to author
libraries that are called directly by the language. Examples in Safe C++
are the iterator support for ranged-for statements,
<code class="sourceCode cpp">send</code>/<code class="sourceCode cpp">sync</code>
for thread safety and the upcoming
<code class="sourceCode cpp">fmt</code> interfaces for f-strings.</p>
<h1 data-number="4" id="conclusion"><span class="header-section-number">4</span> Conclusion<a href="#conclusion" class="self-link"></a></h1>
<p>The US Government is telling industry to stop using C++ for reasons
of national security. Academia is turning away in favor of languages
like Rust and Swift which are built on modern technology. Tech
executives are pushing their organizations to move to Rust.<span class="citation" data-cites="russinovich">[<a href="https://x.com/markrussinovich/status/1571995117233504257?lang=en" role="doc-biblioref">russinovich</a>]</span> All this dilutes the
language’s value to novices. That’s trouble for companies which rely on
a pipeline of new C++ developers to continue their operations.</p>
<p>Instead of being received as a threat, we greet the safety model
developed by Rust as an opportunity to strengthen C++. The Rust
community has spent a decade generating <em>soundness knowledge</em>,
which is the tactics and strategies (interior mutability, send/sync,
borrow checking, and so on) for achieving memory safety without the
overhead of garbage collection. Their investment in soundness knowledge
informs our design of Safe C++. Adopting the same <em>ownership and
borrowing</em> safety model that security professionals have been
pointing to is the sensible and timely way to keep C++ viable for
another generation.</p>
<p>Safe C++ must provide safe alternatives to everything in today’s
Standard Library. This proposal is a healthy beginning but it’s not
comprehensive treatment. Adoption will look daunting to teams that
maintain large applications. However, users aren’t compelled to switch
everything over at once. If you need to stick with some legacy types,
that’s fine. The compiler can’t enforce sound usage of that code, but
that’s always been the case. As developers incorporate more of the safe
standard library, their safety coverage increases. This is not an
all-or-nothing system. Some unsafe code doesn’t mean that your whole
project is unsafe. A project with 50% safe code should have half as many
undetected soundness bugs as a project with no safe code. A project with
99% safe code, as many Rust applications have, should have 1% as many
undetected soundness bugs. Rather than focusing on the long tail of
difficult use cases, we encourage developers to think about the bulk of
code that is amenable to the safety improvements that a mature Safe C++
toolchain will offer.</p>
<p>We’re co-designing the Safe C++ standard library along with the
language extensions. Visit our repository to follow our work. You can
access all the examples included in this document. Or visit our Slack
channel to get involved in the effort:</p>
<blockquote>
<p>Github: <a href="https://github.com/cppalliance/safe-cpp">https://github.com/cppalliance/safe-cpp</a><br />
Slack: <a href="https://cpplang.slack.com/archives/C07GH9NFK0F">https://cpplang.slack.com/archives/C07GH9NFK0F</a><br />
Circle download: <a href="https://www.circle-lang.org/">https://www.circle-lang.org/</a><br />
Working draft: <a href="https://cppalliance.org/safe-cpp/draft.html">https://cppalliance.org/safe-cpp/draft.html</a></p>
</blockquote>
<p>Everything in this proposal took about 18 months to design and
implement in Circle. With participation from industry, we could resolve
the remaining design questions and in another 18 months have a language
and standard library robust enough for mainstream evaluation. While Safe
C++ is a large extension to the language, the cost of building new
tooling is not steep. If C++ continues to go forward without a memory
safety strategy, that’s because institutional users are choosing not to
pursue it; it’s not because memory safe tooling is “impossible” to
build.</p>
<p>An earlier version of this work was presented to SG23 at the St Louis
2024 ISO meeting, with the closing poll “We should promise more
committee time on borrow checking?” — SF: 20, WF: 7, N: 1, WA: 0, SA:
0.</p>
<h1 data-number="5" id="bibliography"><span class="header-section-number">5</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-ante" class="csl-entry" role="doc-biblioentry">
[ante] Ante Shared Interior Mutability. <a href="https://antelang.org/blog/safe_shared_mutability/#shared-interior-mutability"><div class="csl-block">https://antelang.org/blog/safe_shared_mutability/#shared-interior-mutability</div></a>
</div>
<div id="ref-arc" class="csl-entry" role="doc-biblioentry">
[arc] Automatic reference counting. <a href="https://docs.swift.org/swift-book/documentation/the-swift-programming-language/automaticreferencecounting/"><div class="csl-block">https://docs.swift.org/swift-book/documentation/the-swift-programming-language/automaticreferencecounting/</div></a>
</div>
<div id="ref-borrow-checking" class="csl-entry" role="doc-biblioentry">
[borrow-checking] The Rust RFC Book - Non-lexical lifetimes. <a href="https://rust-lang.github.io/rfcs/2094-nll.html"><div class="csl-block">https://rust-lang.github.io/rfcs/2094-nll.html</div></a>
</div>
<div id="ref-cell" class="csl-entry" role="doc-biblioentry">
[cell] Cell. <a href="https://doc.rust-lang.org/std/cell/struct.Cell.html"><div class="csl-block">https://doc.rust-lang.org/std/cell/struct.Cell.html</div></a>
</div>
<div id="ref-cisa-roadmaps" class="csl-entry" role="doc-biblioentry">
[cisa-roadmaps] CISA Releases Joint Guide for Software Manufacturers :
The Case for Memory Safe Roadmaps. <a href="https://www.cisa.gov/news-events/alerts/2023/12/06/cisa-releases-joint-guide-software-manufacturers-case-memory-safe-roadmaps"><div class="csl-block">https://www.cisa.gov/news-events/alerts/2023/12/06/cisa-releases-joint-guide-software-manufacturers-case-memory-safe-roadmaps</div></a>
</div>
<div id="ref-cisa-urgent" class="csl-entry" role="doc-biblioentry">
[cisa-urgent] The Urgent Need for Memory Safety in Software Products. <a href="https://www.cisa.gov/news-events/news/urgent-need-memory-safety-software-products"><div class="csl-block">https://www.cisa.gov/news-events/news/urgent-need-memory-safety-software-products</div></a>
</div>
<div id="ref-clangir" class="csl-entry" role="doc-biblioentry">
[clangir] Upstreaming ClangIR. <a href="https://discourse.llvm.org/t/rfc-upstreaming-clangir/76587"><div class="csl-block">https://discourse.llvm.org/t/rfc-upstreaming-clangir/76587</div></a>
</div>
<div id="ref-clang-lifetime-annotations" class="csl-entry" role="doc-biblioentry">
[clang-lifetime-annotations] Lifetime annotations for the C++ Clang
Frontend. <a href="https://discourse.llvm.org/t/rfc-lifetime-annotations-for-c/61377"><div class="csl-block">https://discourse.llvm.org/t/rfc-lifetime-annotations-for-c/61377</div></a>
</div>
<div id="ref-cve-rs" class="csl-entry" role="doc-biblioentry">
[cve-rs] cve-rs. <a href="https://github.com/Speykious/cve-rs"><div class="csl-block">https://github.com/Speykious/cve-rs</div></a>
</div>
<div id="ref-drop" class="csl-entry" role="doc-biblioentry">
[drop] drop in std::ops. <a href="https://doc.rust-lang.org/std/ops/trait.Drop.html"><div class="csl-block">https://doc.rust-lang.org/std/ops/trait.Drop.html</div></a>
</div>
<div id="ref-gen-kill" class="csl-entry" role="doc-biblioentry">
[gen-kill] Data-flow analysis. <a href="https://en.wikipedia.org/wiki/Data-flow_analysis#Bit_vector_problems"><div class="csl-block">https://en.wikipedia.org/wiki/Data-flow_analysis#Bit_vector_problems</div></a>
</div>
<div id="ref-google-0day" class="csl-entry" role="doc-biblioentry">
[google-0day] 0day <span>“In the Wild.”</span> <a href="https://googleprojectzero.blogspot.com/p/0day.html"><div class="csl-block">https://googleprojectzero.blogspot.com/p/0day.html</div></a>
</div>
<div id="ref-hoare" class="csl-entry" role="doc-biblioentry">
[hoare] Null References: The Billion Dollar Mistake. <a href="https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/"><div class="csl-block">https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/</div></a>
</div>
<div id="ref-how-the-borrow-check-works" class="csl-entry" role="doc-biblioentry">
[how-the-borrow-check-works] How the borrow check works. <a href="https://rust-lang.github.io/rfcs/2094-nll.html#layer-5-how-the-borrow-check-works"><div class="csl-block">https://rust-lang.github.io/rfcs/2094-nll.html#layer-5-how-the-borrow-check-works</div></a>
</div>
<div id="ref-isprint" class="csl-entry" role="doc-biblioentry">
[isprint] std::isprint. <a href="https://en.cppreference.com/w/cpp/string/byte/isprint"><div class="csl-block">https://en.cppreference.com/w/cpp/string/byte/isprint</div></a>
</div>
<div id="ref-itanium-abi" class="csl-entry" role="doc-biblioentry">
[itanium-abi] Itanium C++ ABI: Non-Trivial Parameters. <a href="https://itanium-cxx-abi.github.io/cxx-abi/abi.html#non-trivial-parameters"><div class="csl-block">https://itanium-cxx-abi.github.io/cxx-abi/abi.html#non-trivial-parameters</div></a>
</div>
<div id="ref-matches" class="csl-entry" role="doc-biblioentry">
[matches] matches! macro. <a href="https://doc.rust-lang.org/std/macro.matches.html"><div class="csl-block">https://doc.rust-lang.org/std/macro.matches.html</div></a>
</div>
<div id="ref-may-dangle" class="csl-entry" role="doc-biblioentry">
[may-dangle] dropck_eyepatch. <a href="https://rust-lang.github.io/rfcs/1327-dropck-param-eyepatch.html"><div class="csl-block">https://rust-lang.github.io/rfcs/1327-dropck-param-eyepatch.html</div></a>
</div>
<div id="ref-mir" class="csl-entry" role="doc-biblioentry">
[mir] The MIR (Mid-level IR). <a href="https://rustc-dev-guide.rust-lang.org/mir/index.html"><div class="csl-block">https://rustc-dev-guide.rust-lang.org/mir/index.html</div></a>
</div>
<div id="ref-ms-vulnerabilities" class="csl-entry" role="doc-biblioentry">
[ms-vulnerabilities] We need a safer systems programming language. <a href="https://msrc.microsoft.com/blog/2019/07/we-need-a-safer-systems-programming-language"><div class="csl-block">https://msrc.microsoft.com/blog/2019/07/we-need-a-safer-systems-programming-language</div></a>
</div>
<div id="ref-mutex" class="csl-entry" role="doc-biblioentry">
[mutex] Mutex. <a href="https://doc.rust-lang.org/std/sync/struct.Mutex.html"><div class="csl-block">https://doc.rust-lang.org/std/sync/struct.Mutex.html</div></a>
</div>
<div id="ref-ncsi-plan" class="csl-entry" role="doc-biblioentry">
[ncsi-plan] National Cybersecurity Strategy Implementation Plan. <a href="https://www.whitehouse.gov/wp-content/uploads/2024/05/NCSIP-Version-2-FINAL-May-2024.pdf"><div class="csl-block">https://www.whitehouse.gov/wp-content/uploads/2024/05/NCSIP-Version-2-FINAL-May-2024.pdf</div></a>
</div>
<div id="ref-nsa-guidance" class="csl-entry" role="doc-biblioentry">
[nsa-guidance] NSA Releases Guidance on How to Protect Against Software
Memory Safety Issues. <a href="https://www.nsa.gov/Press-Room/News-Highlights/Article/Article/3215760/nsa-releases-guidance-on-how-to-protect-against-software-memory-safety-issues/"><div class="csl-block">https://www.nsa.gov/Press-Room/News-Highlights/Article/Article/3215760/nsa-releases-guidance-on-how-to-protect-against-software-memory-safety-issues/</div></a>
</div>
<div id="ref-P1144R11" class="csl-entry" role="doc-biblioentry">
[P1144R11] Arthur O’Dwyer. 2024-05-15. std::is_trivially_relocatable. <a href="https://wg21.link/p1144r11"><div class="csl-block">https://wg21.link/p1144r11</div></a>
</div>
<div id="ref-P1179R1" class="csl-entry" role="doc-biblioentry">
[P1179R1] Herb Sutter. 2019-11-22. Lifetime safety: Preventing common
dangling. <a href="https://wg21.link/p1179r1"><div class="csl-block">https://wg21.link/p1179r1</div></a>
</div>
<div id="ref-P2688R1" class="csl-entry" role="doc-biblioentry">
[P2688R1] Michael Park. 2024-02-15. Pattern Matching: `match`
Expression. <a href="https://wg21.link/p2688r1"><div class="csl-block">https://wg21.link/p2688r1</div></a>
</div>
<div id="ref-P3166R0" class="csl-entry" role="doc-biblioentry">
[P3166R0] Lewis Baker. 2024-03-16. Static Exception Specifications. <a href="https://wg21.link/p3166r0"><div class="csl-block">https://wg21.link/p3166r0</div></a>
</div>
<div id="ref-phantom-data" class="csl-entry" role="doc-biblioentry">
[phantom-data] PhantomData. <a href="https://doc.rust-lang.org/nomicon/phantom-data.html"><div class="csl-block">https://doc.rust-lang.org/nomicon/phantom-data.html</div></a>
</div>
<div id="ref-pin" class="csl-entry" role="doc-biblioentry">
[pin] Module std::pin. <a href="https://doc.rust-lang.org/std/pin/index.html"><div class="csl-block">https://doc.rust-lang.org/std/pin/index.html</div></a>
</div>
<div id="ref-raii" class="csl-entry" role="doc-biblioentry">
[raii] Resource acquisition is initialization. <a href="https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization"><div class="csl-block">https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization</div></a>
</div>
<div id="ref-ref-cell" class="csl-entry" role="doc-biblioentry">
[ref-cell] RefCell. <a href="https://doc.rust-lang.org/std/cell/struct.RefCell.html"><div class="csl-block">https://doc.rust-lang.org/std/cell/struct.RefCell.html</div></a>
</div>
<div id="ref-russinovich" class="csl-entry" role="doc-biblioentry">
[russinovich] It’s time to start halting any new projects in C/C++ and
use Rust. <a href="https://x.com/markrussinovich/status/1571995117233504257?lang=en"><div class="csl-block">https://x.com/markrussinovich/status/1571995117233504257?lang=en</div></a>
</div>
<div id="ref-rust-iterator" class="csl-entry" role="doc-biblioentry">
[rust-iterator] Iterator in std::iter. <a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html"><div class="csl-block">https://doc.rust-lang.org/std/iter/trait.Iterator.html</div></a>
</div>
<div id="ref-rust-language" class="csl-entry" role="doc-biblioentry">
[rust-language] The Rust Programming Language. <a href="https://doc.rust-lang.org/book/"><div class="csl-block">https://doc.rust-lang.org/book/</div></a>
</div>
<div id="ref-rwlock" class="csl-entry" role="doc-biblioentry">
[rwlock] RwLock. <a href="https://doc.rust-lang.org/std/sync/struct.RwLock.html"><div class="csl-block">https://doc.rust-lang.org/std/sync/struct.RwLock.html</div></a>
</div>
<div id="ref-safety-comments" class="csl-entry" role="doc-biblioentry">
[safety-comments] Safety comments policy. <a href="https://std-dev-guide.rust-lang.org/policy/safety-comments.html"><div class="csl-block">https://std-dev-guide.rust-lang.org/policy/safety-comments.html</div></a>
</div>
<div id="ref-safe-unsafe-meaning" class="csl-entry" role="doc-biblioentry">
[safe-unsafe-meaning] How Safe and Unsafe Interact. <a href="https://doc.rust-lang.org/nomicon/safe-unsafe-meaning.html"><div class="csl-block">https://doc.rust-lang.org/nomicon/safe-unsafe-meaning.html</div></a>
</div>
<div id="ref-scc" class="csl-entry" role="doc-biblioentry">
[scc] Strongly connected component. <a href="https://en.wikipedia.org/wiki/Strongly_connected_component"><div class="csl-block">https://en.wikipedia.org/wiki/Strongly_connected_component</div></a>
</div>
<div id="ref-secure-by-design" class="csl-entry" role="doc-biblioentry">
[secure-by-design] Secure by Design : Google’s Perspective on Memory
Safety. <a href="https://research.google/pubs/secure-by-design-googles-perspective-on-memory-safety/"><div class="csl-block">https://research.google/pubs/secure-by-design-googles-perspective-on-memory-safety/</div></a>
</div>
<div id="ref-send-sync" class="csl-entry" role="doc-biblioentry">
[send-sync] Rustnomicon – Send and Sync. <a href="https://doc.rust-lang.org/nomicon/send-and-sync.html"><div class="csl-block">https://doc.rust-lang.org/nomicon/send-and-sync.html</div></a>
</div>
<div id="ref-sil" class="csl-entry" role="doc-biblioentry">
[sil] Swift Intermediate Language (SIL). <a href="https://github.com/swiftlang/swift/blob/main/docs/SIL.rst"><div class="csl-block">https://github.com/swiftlang/swift/blob/main/docs/SIL.rst</div></a>
</div>
<div id="ref-string-view-use-after-free" class="csl-entry" role="doc-biblioentry">
[string-view-use-after-free] std::string_view encourages use-after-free;
the Core Guidelines Checker doesn’t complain. <a href="https://github.com/isocpp/CppCoreGuidelines/issues/1038"><div class="csl-block">https://github.com/isocpp/CppCoreGuidelines/issues/1038</div></a>
</div>
<div id="ref-taming-the-wildcards" class="csl-entry" role="doc-biblioentry">
[taming-the-wildcards] Taming the Wildcards: Combining Definition- and
Use-Site Variance. <a href="https://yanniss.github.io/variance-pldi11.pdf"><div class="csl-block">https://yanniss.github.io/variance-pldi11.pdf</div></a>
</div>
<div id="ref-tracing-gc" class="csl-entry" role="doc-biblioentry">
[tracing-gc] Tracing garbage collection. <a href="https://en.wikipedia.org/wiki/Tracing_garbage_collection"><div class="csl-block">https://en.wikipedia.org/wiki/Tracing_garbage_collection</div></a>
</div>
<div id="ref-unsafe-cell" class="csl-entry" role="doc-biblioentry">
[unsafe-cell] UnsafeCell. <a href="https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html"><div class="csl-block">https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html</div></a>
</div>
<div id="ref-unwinding-puts-limits-on-the-borrow-checker" class="csl-entry" role="doc-biblioentry">
[unwinding-puts-limits-on-the-borrow-checker] Unwinding puts limits on
the borrow checker. <a href="https://smallcultfollowing.com/babysteps/blog/2024/05/02/unwind-considered-harmful/#unwinding-puts-limits-on-the-borrow-checker"><div class="csl-block">https://smallcultfollowing.com/babysteps/blog/2024/05/02/unwind-considered-harmful/#unwinding-puts-limits-on-the-borrow-checker</div></a>
</div>
<div id="ref-variance" class="csl-entry" role="doc-biblioentry">
[variance] RFC 0738 - variance. <a href="https://rust-lang.github.io/rfcs/0738-variance.html"><div class="csl-block">https://rust-lang.github.io/rfcs/0738-variance.html</div></a>
</div>
<div id="ref-vocabulary-types" class="csl-entry" role="doc-biblioentry">
[vocabulary-types] CXX — safe interop between Rust and C++. <a href="https://cxx.rs/bindings.html"><div class="csl-block">https://cxx.rs/bindings.html</div></a>
</div>
<div id="ref-white-house" class="csl-entry" role="doc-biblioentry">
[white-house] Future Software Should Be Memory Safe. <a href="https://www.whitehouse.gov/oncd/briefing-room/2024/02/26/press-release-technical-report/"><div class="csl-block">https://www.whitehouse.gov/oncd/briefing-room/2024/02/26/press-release-technical-report/</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
