Skip to content

Commit be5fe7c

Browse files
committed
Added November note
1 parent 5e33984 commit be5fe7c

File tree

2 files changed

+95
-6
lines changed

2 files changed

+95
-6
lines changed

docs/draft.html

+64-6
Original file line numberDiff line numberDiff line change
@@ -484,10 +484,12 @@ <h1 id="toctitle">Contents</h1>
484484
<li><a href="#unresolved-design-issues" id="toc-unresolved-design-issues"><span class="toc-section-number">2.8</span> Unresolved design
485485
issues<span></span></a></li>
486486
</ul></li>
487-
<li><a href="#implementation-guidance" id="toc-implementation-guidance"><span class="toc-section-number">3</span> Implementation
487+
<li><a href="#post-submission-developments" id="toc-post-submission-developments"><span class="toc-section-number">3</span> Post-submission
488+
developments<span></span></a></li>
489+
<li><a href="#implementation-guidance" id="toc-implementation-guidance"><span class="toc-section-number">4</span> Implementation
488490
guidance<span></span></a></li>
489-
<li><a href="#conclusion" id="toc-conclusion"><span class="toc-section-number">4</span> Conclusion<span></span></a></li>
490-
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">5</span> References<span></span></a></li>
491+
<li><a href="#conclusion" id="toc-conclusion"><span class="toc-section-number">5</span> Conclusion<span></span></a></li>
492+
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">6</span> References<span></span></a></li>
491493
</ul>
492494
</div>
493495
<h1 data-number="1" id="introduction"><span class="header-section-number">1</span> Introduction<a href="#introduction" class="self-link"></a></h1>
@@ -3240,6 +3242,8 @@ <h3 data-number="2.2.11" id="lifetimes-and-templates"><span class="header-sectio
32403242
bound lifetime template parameters with the <code class="sourceCode cpp"><span class="kw">typename</span> T<span class="op">+</span></code>
32413243
syntax. It’s not done for all template parameters, because that would
32423244
interfere with C++’s partial and explicit specialization facilities.</p>
3245+
<p><strong>(See <a href="#post-submission-developments">post-submission
3246+
note</a> from November 2024)</strong></p>
32433247
<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>
32443248
<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>
32453249
<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>
@@ -4734,7 +4738,61 @@ <h3 data-number="2.8.4" id="relocation-out-of-references"><span class="header-se
47344738
analysis.</p>
47354739
<p>This extended relocation feature is some of the ripest low-hanging
47364740
fruit for improving the safety experience in Safe C++.</p>
4737-
<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>
4741+
<h1 data-number="3" id="post-submission-developments"><span class="header-section-number">3</span> Post-submission developments<a href="#post-submission-developments" class="self-link"></a></h1>
4742+
<p><strong>November 2024:</strong></p>
4743+
<p>The treatment of lifetime binder template parameters can be greatly
4744+
simplified by dropping the <a href="#lifetimes-and-templates"><code class="sourceCode cpp"><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">+&gt;</span></code></a>
4745+
syntax and <em>always</em> generating lifetime template parameters when
4746+
used in class or function templates. This is discussed in a <a href="https://github.com/cppalliance/safe-cpp/issues/12">Github
4747+
Issue</a>.</p>
4748+
<p>We can walk through the formerly problematic case of
4749+
<code class="sourceCode cpp">std<span class="op">::</span>is_same</code>.
4750+
We want the partial selected even when the specialization’s template
4751+
arguments have lifetime binders.</p>
4752+
<div class="sourceCode" id="cb91"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb91-1"><a href="#cb91-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>is_same<span class="op">&lt;</span><span class="dt">int</span><span class="op">^</span>, <span class="dt">int</span><span class="op">^&gt;::</span>value;</span>
4753+
<span id="cb91-2"><a href="#cb91-2" aria-hidden="true" tabindex="-1"></a></span>
4754+
<span id="cb91-3"><a href="#cb91-3" aria-hidden="true" tabindex="-1"></a><span class="co">// Implicitly add placeholders to unbound binders in class template arguments.</span></span>
4755+
<span id="cb91-4"><a href="#cb91-4" aria-hidden="true" tabindex="-1"></a><span class="co">// The above transforms to:</span></span>
4756+
<span id="cb91-5"><a href="#cb91-5" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>is_same<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>value; </span>
4757+
<span id="cb91-6"><a href="#cb91-6" aria-hidden="true" tabindex="-1"></a></span>
4758+
<span id="cb91-7"><a href="#cb91-7" aria-hidden="true" tabindex="-1"></a><span class="co">// During normalization, replace lifetime arguments with invented</span></span>
4759+
<span id="cb91-8"><a href="#cb91-8" aria-hidden="true" tabindex="-1"></a><span class="co">// template lifetime parameters. </span></span>
4760+
<span id="cb91-9"><a href="#cb91-9" aria-hidden="true" tabindex="-1"></a><span class="co">// If the complete template was chosen (but it won&#39;t be), you&#39;d get:</span></span>
4761+
<span id="cb91-10"><a href="#cb91-10" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>is_same<span class="op">&lt;</span><span class="dt">int</span><span class="op">^/</span><span class="er">#T0, int^/#T1&gt;/_/_::value</span></span></code></pre></div>
4762+
<p>The <code class="sourceCode cpp">is_same</code> specialization is
4763+
created with two <em>proxy lifetimes</em>. When a complete type is
4764+
needed the compiler searches for the best partial or explicit
4765+
specialization. This will now involve stripping all lifetime binders.
4766+
<code class="sourceCode cpp"><span class="dt">int</span><span class="op">^/</span><span class="er">#T0</span></code>
4767+
and <code class="sourceCode cpp"><span class="dt">int</span><span class="op">^/</span><span class="er">#T1</span></code>
4768+
are different types, but after being stripped, you’re left with <code class="sourceCode cpp"><span class="dt">int</span><span class="op">^</span></code>
4769+
and <code class="sourceCode cpp"><span class="dt">int</span><span class="op">^</span></code>
4770+
which are the same type. They’ll match the partial specialization when
4771+
that’s also stripped of its proxy lifetimes.</p>
4772+
<p>The template arguments of the partial or explicit specialization have
4773+
different lifetimes than the template arguments of the complete
4774+
template. But this should be expected: the template arguments of partial
4775+
or explicit specializations are already different than the primary
4776+
template’s. Outside of the template definition, users always refer to
4777+
the specialization through the template arguments on the complete
4778+
template. That remains the case in this modification.</p>
4779+
<p>If a partial or explicit specialization is chosen, that could be
4780+
regarded as a loss of information, since two invented lifetime
4781+
parameters that were independent get collapsed into one. Fortunately
4782+
this doesn’t compromise safety since borrow checking is performed after
4783+
instantiation on complete templates. It was misguided for me to worry
4784+
about the loss of lifetime independence that would result from partial
4785+
specialization, since why else would the class provide those
4786+
specializations if they didn’t want them to be used?</p>
4787+
<p>We should also revise the policy for using lifetime parameters in
4788+
class definitions. Named lifetimes must be used by non-static data
4789+
members, or else the definition is ill-formed. Template lifetime
4790+
parameters, which are implicit, need not be used by non-static data
4791+
members. These are <em>unbound lifetimes</em>, and that should be okay.
4792+
The lifetimes in the specialization of
4793+
<code class="sourceCode cpp">std<span class="op">::</span>is_same</code>
4794+
don’t mean anything, and can be safely ignored.</p>
4795+
<h1 data-number="4" id="implementation-guidance"><span class="header-section-number">4</span> Implementation guidance<a href="#implementation-guidance" class="self-link"></a></h1>
47384796
<p>The intelligence behind the <em>ownership and borrowing</em> safety
47394797
model resides in the compiler’s middle-end, in its <em>MIR analysis</em>
47404798
passes. The first thing compiler engineers should focus on when pursuing
@@ -4879,7 +4937,7 @@ <h1 data-number="3" id="implementation-guidance"><span class="header-section-num
48794937
<code class="sourceCode cpp">send</code>/<code class="sourceCode cpp">sync</code>
48804938
for thread safety and the upcoming
48814939
<code class="sourceCode cpp">fmt</code> interfaces for f-strings.</p>
4882-
<h1 data-number="4" id="conclusion"><span class="header-section-number">4</span> Conclusion<a href="#conclusion" class="self-link"></a></h1>
4940+
<h1 data-number="5" id="conclusion"><span class="header-section-number">5</span> Conclusion<a href="#conclusion" class="self-link"></a></h1>
48834941
<p>The US Government is telling industry to stop using C++ for reasons
48844942
of national security. Academia is turning away in favor of languages
48854943
like Rust and Swift which are built on modern technology. Tech
@@ -4935,7 +4993,7 @@ <h1 data-number="4" id="conclusion"><span class="header-section-number">4</span>
49354993
2024 ISO meeting, with the closing poll “We should promise more
49364994
committee time on borrow checking?” — SF: 20, WF: 7, N: 1, WA: 0, SA:
49374995
0.</p>
4938-
<h1 data-number="5" id="bibliography"><span class="header-section-number">5</span> References<a href="#bibliography" class="self-link"></a></h1>
4996+
<h1 data-number="6" id="bibliography"><span class="header-section-number">6</span> References<a href="#bibliography" class="self-link"></a></h1>
49394997
<div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="1" role="doc-bibliography">
49404998
<div id="ref-ante" class="csl-entry" role="doc-biblioentry">
49414999
[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>

proposal/draft.md

+31
Original file line numberDiff line numberDiff line change
@@ -1821,6 +1821,8 @@ A class template's instantiation doesn't depend on the lifetimes of its users. `
18211821
18221822
In the current safety model, this transformation only occurs for bound lifetime template parameters with the `typename T+` syntax. It's not done for all template parameters, because that would interfere with C++'s partial and explicit specialization facilities.
18231823
1824+
**(See [post-submission note](#post-submission-developments) from November 2024)**
1825+
18241826
```cpp
18251827
template<typename T0, typename T1>
18261828
struct is_same {
@@ -2740,6 +2742,35 @@ It's already possible to write C++ code that is less burdened by cleanup paths t
27402742
27412743
This extended relocation feature is some of the ripest low-hanging fruit for improving the safety experience in Safe C++.
27422744
2745+
# Post-submission developments
2746+
2747+
**November 2024:**
2748+
2749+
The treatment of lifetime binder template parameters can be greatly simplified by dropping the [`<typename T+>`](#lifetimes-and-templates) syntax and _always_ generating lifetime template parameters when used in class or function templates. This is discussed in a [Github Issue](https://github.com/cppalliance/safe-cpp/issues/12).
2750+
2751+
We can walk through the formerly problematic case of `std::is_same`. We want the partial selected even when the specialization's template arguments have lifetime binders.
2752+
2753+
```cpp
2754+
std::is_same<int^, int^>::value;
2755+
2756+
// Implicitly add placeholders to unbound binders in class template arguments.
2757+
// The above transforms to:
2758+
std::is_same<int^/_, int^_>::value;
2759+
2760+
// During normalization, replace lifetime arguments with invented
2761+
// template lifetime parameters.
2762+
// If the complete template was chosen (but it won't be), you'd get:
2763+
std::is_same<int^/#T0, int^/#T1>/_/_::value
2764+
```
2765+
2766+
The `is_same` specialization is created with two _proxy lifetimes_. When a complete type is needed the compiler searches for the best partial or explicit specialization. This will now involve stripping all lifetime binders. `int^/#T0` and `int^/#T1` are different types, but after being stripped, you're left with `int^` and `int^` which are the same type. They'll match the partial specialization when that's also stripped of its proxy lifetimes.
2767+
2768+
The template arguments of the partial or explicit specialization have different lifetimes than the template arguments of the complete template. But this should be expected: the template arguments of partial or explicit specializations are already different than the primary template's. Outside of the template definition, users always refer to the specialization through the template arguments on the complete template. That remains the case in this modification.
2769+
2770+
If a partial or explicit specialization is chosen, that could be regarded as a loss of information, since two invented lifetime parameters that were independent get collapsed into one. Fortunately this doesn't compromise safety since borrow checking is performed after instantiation on complete templates. It was misguided for me to worry about the loss of lifetime independence that would result from partial specialization, since why else would the class provide those specializations if they didn't want them to be used?
2771+
2772+
We should also revise the policy for using lifetime parameters in class definitions. Named lifetimes must be used by non-static data members, or else the definition is ill-formed. Template lifetime parameters, which are implicit, need not be used by non-static data members. These are _unbound lifetimes_, and that should be okay. The lifetimes in the specialization of `std::is_same` don't mean anything, and can be safely ignored.
2773+
27432774
# Implementation guidance
27442775

27452776
The intelligence behind the _ownership and borrowing_ safety model resides in the compiler's middle-end, in its _MIR analysis_ 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,[@sil] Rust passes through MIR,[@mir] and Circle passes through it's mid-level IR when targeting the new object model. There is an effort called ClangIR[@clangir] 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.

0 commit comments

Comments
 (0)