<!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>Date:</th>
        <td>2018-10-08</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, Evolution</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>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
N4762 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>The first option has the benefit of keeping our options open. It will be possible to choose a different solution in the future without breaking or changing the behavior of code that is valid under that option. It is also clearly implementable with clear semantics. As such, this paper provides a proposed resolution (for the consideration of CWG) for the subject issue that implements Option 1.</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.4 [dcl.spec.auto] paragraph 9.
Technically, the prohibition could be lifted for preconditions as well as for postconditions.</p>

<h2>Proposed resolution for consideration by CWG</h2>
<p>The editing instructions within this document use N4762 as its base wording.</p>

<div><input type="checkbox" id="xins1" /><label for="xins1">Hide inserted text</label>
<input type="checkbox" id="xdel1" /><label for="xdel1">Hide deleted text</label><!--

--><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
> The optional <i>identifier</i> shall not be present when the declared return type of the function contains a placeholder type (9.1.7.4 [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
></div>

<h2>Additional discussion points</h2>

<p>The first option impacts expressiveness. Should we adopt some form of constrained type specifiers, this option would prohibit applying a postcondition on interfaces expressed with a constrained return type. For example (using the <code>Concept auto</code> syntax):</p>
<pre class="example prettyprint language-cpp"><code
>Integral auto getWeight() const
  [[ensures res: minWeight &lt;= res &amp;&amp; res &lt;= maxWeight]] </code><i>// error</i><code>
{
  return 0u;
}</code></pre>

<p>The second option introduces complications around the set of declarations available for name lookup in the predicate of affected contracts. The postcondition effectively becomes a template definition, and template-like considerations come into play. For example:</p>
<pre class="example prettyprint language-cpp"><code
>bool checkGlobalState(int);
auto foo()
  [[ensures res: checkGlobalState(42u) &amp;&amp; checkResult(res)]]; </code><i
  >// okay; note: <code>checkGlobalState</code> resolved at "definition"</i><code>

bool checkResult(int);
auto foo()
  { return 42u; } </code><i>// okay; <code>checkResult</code> above resolved at "point-of-instantiation" here</i><code>

bool checkResult(unsigned);

auto foo()
  [[ensures res: checkGlobalState(42u) &amp;&amp; checkResult(res)]]; </code><i
  >// okay?; <code>checkResult</code> still resolved at "point-of-instantiation"</i><code>

bool checkGlobalState(unsigned);

auto foo()
  [[ensures res: checkGlobalState(42u) &amp;&amp; checkResult(res)]]; </code><i
  >// error: <code>checkGlobalState</code> resolved at new "definition" here</i></pre>

<p>The third option has a limitation that the first declaration of an affected non-templated function would need to be a definition. It also increases the differences between templated and non-templated functions; namely, the templated cases may be forward declared. It has the advantage of avoiding the addition of more template-like considerations to the non-template cases.</p>

<p>The fourth option avoids the difference between the templated and non-templated cases of the third option except to admit avoidance of disambiguators where the first declaration of a non-templated function is a definition. It retains the template-like considerations for non-template cases involved in the second option.</p>

<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>
