<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US"><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Contract postconditions and return type deduction</title>

<style type="text/css">
body { color: #000000; background-color: #FFFFFF; max-width: 40em; }
del, .del { text-decoration: line-through; color: #8B0040; }
ins, .ins { text-decoration: underline; color: #005100; }

p.example { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }

code.extract { background-color: #F5F6A2; }
pre.extract { margin-left: 2em; background-color: #F5F6A2;
  border: 1px solid #E1E28E; }

p.function { }
.attribute { margin-left: 2em; }
.attribute dt { float: left; font-style: italic;
  padding-right: 1ex; }
.attribute dd { margin-left: 0em; }

blockquote.std, ul.std { color: #000000; background-color: #F1F1F1;
  border: 1px solid #D1D1D1;
  padding-left: 0.5em; padding-right: 0.5em; }
blockquote.std del, blockquote.std .del, ul.std del, ul.std .del { text-decoration: line-through;
  color: #000000; background-color: #FFEBFF;
  border: 1px solid #ECD7EC; }
blockquote.std ins, blockquote.std .ins, ul.std ins, ul.std .ins { text-decoration: underline;
  color: #000000; background-color: #C8FFC8; }
blockquote.stddel { text-decoration: line-through;
  color: #000000; background-color: #FFEBFF;
  border: 1px solid #ECD7EC;
  padding-left: 0.5em; padding-right: 0.5em; }
blockquote.stdins { text-decoration: none;
  color: #000000; background-color: #C8FFC8;
  border: 1px solid #B3EBB3;
  padding-left: 0.5em; padding-right: 0.5em; }

table { border: 1px solid black; border-spacing: 0px;
  margin-left: auto; margin-right: auto; }
th { text-align: left; vertical-align: top;
  padding-left: 0.8em; border: none; }
td { text-align: left; vertical-align: top;
  padding-left: 0.8em; border: none; }

table.table { border-spacing: 2px; border-collapse: separate; }
.table * th, .table * td { border: 1px solid black; }

table.frontmatter { border: 0; border-spacing: 0px; border-collapse: collapse; margin: 0; width: 619px; }
.frontmatter * td, .frontmatter * th { padding: 0px; }
.frontmatter * th { font-weight: inherit; text-align: left; vertical-align: top; }

ul.dash { list-style-type: none; }
ul.dash li:before { content: '\2014'; margin-left: -1em }

span.highlight { background-color: #7FDFFF }

.nowrap { white-space: nowrap; }
.pre { white-space: pre; }

pre { font-family: inherit; }

#xins1:checked ~ * ins { display: none; visibility: hidden }
#xdel1:checked ~ * del { display: none; visibility: hidden }
#xins2:checked ~ * ins { display: none; visibility: hidden }
#xdel2:checked ~ * del { display: none; visibility: hidden }
</style>

<script type="text/javascript" src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
</head>

<body>
<h1>Contract postconditions and return type deduction</h1>
<table class="frontmatter"><tbody>
    <tr>
        <th>Document number:</th>
        <td>P1323R1</td>
    </tr>
    <tr>
        <th>Date:</th>
        <td>2019-01-19</td>
    </tr>
    <tr>
        <th>Project:</th>
        <td>ISO/IEC JTC 1/SC 22/WG 21/C++</td>
    </tr>
    <tr>
        <th>Audience subgroup:</th>
        <td>Core</td>
    </tr>
    <tr>
        <th>Revises:</th>
        <td>P1323R0</td>
    </tr>
    <tr>
        <th>Reply-to:</th>
        <td><span class="nowrap">Hubert S.K. Tong</span> &lt;<a href="mailto:hubert.reinterpretcast@gmail.com">hubert.reinterpretcast@gmail.com</a>&gt;</td>
    </tr>
</tbody></table>

<h2>Changelog</h2>
<h3>Changes from R0</h3>
<ul><li>Pruned discussion points; added summary of the EWG direction instead.</li>
<li>Added wording to implement the EWG direction for resolving the issue of parsing needing lookup.</li>
<li>Added wording to implement the EWG direction to enable recursive calls from both preconditions and postconditions.</li>
</ul>

<h2>Issue Description</h2>
<p>The interaction between return type deduction and contract postconditions was not raised in the review of the latter feature.
Since this introduces the possibility of types and names dependent upon return type deduction, we have a noticeable lack of wording.</p>

<p>Consider:</p>
<pre class="example prettyprint language-cpp"><code
>template &lt;typename&gt; struct Tricky { enum { Nested }; };
template &lt;&gt; struct Tricky&lt;int&gt; { struct Nested { }; };
auto foo()
  [[ ensures ret :
      sizeof(Tricky&lt;decltype(ret)&gt;::Nested) ]] </code><i>// typename?</i><code>
{
  return 42;
}</code></pre>

<p>It has been brought up that the postcondition could not be analyzed in forward declarations in such a situation.</p>

<p>Somewhat separately, recursive calls appearing within the postcondition are currently ill-formed by
N4791 subclause 9.11.4.2 [dcl.attr.contract.cond] paragraph 4, which states that the semantic restrictions of a contract condition is the same as if it appeared
as the first <i>expression-statement</i> in the body of the function.</p>

<h2>Possible solutions</h2>

<p>Techniques we have for dealing with the apparent parsing issue include using disambiguators in the style of handling dependent names and delayed parsing.
Delayed parsing is already necessary for contract conditions of class members declared within the definition of the class since such contract conditions are complete-class contexts. For templates, the return type cannot be deduced until instantiation; therefore, delayed parsing is not sufficient if an abstract syntax tree is to be formed for the template definition (which various implementations rely on in practice).</p>

<p>The following is an enumeration of possible solutions from Richard Smith:</p>
<ol><li>Disallow naming the return value in a postcondition if the function has a deduced return type.</li>
<li>Allow such naming, but treat the name of the return value as having a dependent type. This means requiring <code>template</code> and <code>typename</code> disambiguators; behavior would be as if the point of instantiation is wherever the definition of the function occurs.</li>
<li>Allow such naming as above for templated functions, and for non-templated functions, allow such naming only for definitions. Delaying the parsing of the postcondition until the return type is known is a possible implementation strategy for the non-templated function case of this option.</li>
<li>Allow such naming as above, but apply the dependent-type option for non-templated forward declarations.</li>
</ol>

<p>Notice that a name introduced for the return value associated with a templated entity declared with a deduced return type is type dependent for all options aside from the first (where introducing such a name is ill-formed).</p>

<p>As to the recursive call prohibition: it could be lifted, but the wording is not presented here.
Recursive calls to functions subject to return type deduction are already allowed under 9.1.7.5 [dcl.spec.auto] paragraph 10.
Technically, the prohibition could be lifted for preconditions as well as for postconditions.</p>

<h2>Summary of the EWG Direction</h2>

<p>The EWG discussion settled upon the third option presented.
For templated functions with deduced return types, this means that the return value may be named without additional restrictions except that the name of the return value is treated as having a dependent type.
For the non-templated functions with deduced return types, this means that naming the return value is prohibited except for definitions.
The limitations imposed by the first option, as discussed in the R0 version of this paper, was a factor.
The second and fourth options were not chosen because they involve the cost of introducing semantics similar to that of template-dependency in non-template contexts.</p>

<p>EWG was asked about, and gave no objection to, resolving the recursive call prohibition for both preconditions and postconditions.</p>

<h2>Proposed resolution</h2>
<p>The editing instructions within this document use N4791 as its base wording.</p>

<p>Modify subclause 9.11.4.1 [dcl.attr.contract.syn] paragraph 3:</p>
<blockquote class="std"><p
>A <i>contract-attribute-specifier</i> using <code>ensures</code> is a <i>postcondition</i>.
It expresses a condition that a function should ensure for the return value and/or the state of objects
using a predicate that is intended to hold upon exit from the function.
The attribute may be applied to the function type of a function declaration.
A postcondition may introduce an identifier to represent the glvalue result or the prvalue result object of the function.<ins
> Except for templated functions, the optional <i>identifier</i> shall not be present in non-defining declarations when the declared return type of the function contains a placeholder type (9.1.7.5 [dcl.spec.auto]).</ins>
[<i>Example</i>:</p
><p class="example pre"><code
>int f(char * c)
  [[ensures res: res &gt; 0 &amp;&amp; c != nullptr]];
int g(double * p)
  [[ensures audit res: res != 0 &amp;&amp; p != nullptr &amp;&amp; *p &lt;= 0.0]];</code></p
><p><i>&#x2014;end example</i>]</p></blockquote>

<p>Modify subclause 9.11.4.2 [dcl.attr.contract.cond] paragraph 4:</p>
<blockquote class="std"><p
><ins>For a contract condition associated with a function whose declared return type contains a placeholder type,
the placeholder type is not considered undeduced within the predicate of the contract condition.</ins>
The predicate of a contract condition <ins>otherwise </ins>has the same semantic restrictions as if it appeared as the first
<i>expression-statement</i> in the body of the function it applies to.</p></blockquote>

<p>Modify subclause 12.7.2.2 [temp.dep.expr] paragraph 3:</p>
<blockquote class="std"><p
>An <i>id-expression</i> is type-dependent if it contains</p>
<ul><li>[ &#x2026; ]</li>
<li>an <i>identifier</i> associated by name lookup with [ &#x2026; ],</li>
<li>the <i>identifier</i> <code>__func__</code> ([dcl.fct.def.general]), [ &#x2026; ],</li>
<li class="ins">within the <i>conditional-expression</i> of a postcondition ([dcl.attr.contract])
associated with a templated function whose declared return type contains a placeholder type,
the <i>identifier</i> introduced to represent the result of the function (if any),</li>
<li>[ &#x2026; ]</li>
</ul><p
>[ &#x2026; ]</p></blockquote>

<h2>Acknowledgements</h2>
<p>The author would like to thank Aaron Ballman, Jens Maurer, Richard Smith, and Ville Voutilainen for their feedback on the subject of this paper.
As usual, any remaining mistakes are the responsibility of the author.</p>
</body></html>
