
<!DOCTYPE html>
<html lang="en"><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

<style>
pre {font-family: "Consolas", "Lucida Console", monospace; margin-left:20pt; }
code {font-family: "Consolas", "Lucida Console", monospace; }
pre > i   { font-family: "Consolas", "Lucida Console", monospace;  font-style:italic; }
code > i  { font-family: "Consolas", "Lucida Console", monospace;  font-style:italic; }
pre > em  { font-family: "Consolas", "Lucida Console", monospace;  font-style:italic; }
code > em { font-family: "Consolas", "Lucida Console", monospace;  font-style:italic; }
dl > dt { font-style:italic; }
body { font-family: "Calibri" }

@media (prefers-color-scheme: dark) {
	body { background: #111; color:  #ccc; }
	a { color:  #38f; }
	a:visited { color:  #a4d; }
	.sect { color:  #ccc; }
    del { text-decoration: line-through; color: #EE9999; }
    ins { text-decoration: underline; color: #99EE99; }
    blockquote.std    { color: #ccc; background-color: #2A2A2A;  border: 1px solid #3A3A3A;  padding-left: 0.5em; padding-right: 0.5em; }
    blockquote.stddel { text-decoration: line-through;  color: #ccc; background-color: #221820;  border: 1px solid #332228;  padding-left: 0.5em; padding-right: 0.5em; ; }
    blockquote.stdins { text-decoration: underline;  color: #ccc; background-color: #182220;  border: 1px solid #223328; padding: 0.5em; }
    table { border: 1px solid #ccc; border-spacing: 0px;  margin-left: auto; margin-right: auto; }
}

@media (prefers-color-scheme: light) {
	body { background:  white; color: black; }
    del { text-decoration: line-through; color: #8B0040; }
    ins { text-decoration: underline; color: #005100; }
    blockquote.std    { color: #000000; background-color: #F1F1F1;  border: 1px solid #D1D1D1;  padding-left: 0.5em; padding-right: 0.5em; }
    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: underline;  color: #000000; background-color: #C8FFC8;  border: 1px solid #B3EBB3; padding: 0.5em; }
    table { border: 1px solid black; border-spacing: 1px;  margin-left: auto; margin-right: auto; }
}


.comment em { font-family: "Calibri"; font-style:italic; }
p.example   { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }
div.poll { 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; }

.editor { color: #4444BB; font-style: normal; background-color: #DDDDDD; }

tab { padding-left: 4em; }
tab3 { padding-left: 3em; }

.link { float: right; font-family: "Consolas", "Lucida Console", monospace; font-size:80% }


table.header { border: none; border-spacing: 0;  margin-left: 0px; font-style: normal; }
td.header { border: none; border-spacing: 0;  margin-left: 0px; font-style: normal; }
.header { border: none; border-spacing: 0;  margin-left: 0px; font-style: normal; }
table.poll { border: 1px solid black; border-spacing: 0px;  margin-left: 0px; font-style: normal; }

th { text-align: left; vertical-align: top;  padding-left: 0.4em;  /*padding-right: 0.4em; border-bottom:1px dashed;*/ }
td { text-align: left;  padding-left: 0.4em; padding-right: 0.4em; /*border-right:1px dashed; */}
tr { border: solid; border-width: 1px 0; border-bottom:1px solid blue }


.revision   { /*color: #005599;*/ }
.grammar { list-style-type:none }

</style>

<title>Observed a contract violation? Skip subsequent assertions!</title>

</head>
<body>  

<table class="header"><tbody>
  <tr>
    <th>Document number:&nbsp;&nbsp;</th><th> </th><td class="header">P3582R0</td>
  </tr>
  <tr>
    <th>Date:&nbsp;&nbsp;</th><th> </th><td class="header">2025-01-13</td>
  </tr>
  <tr>
    <th>Audience:&nbsp;&nbsp;</th><th> </th><td class="header">SG21, EWG</td>
  </tr>
  <tr>
    <th>Reply-to:&nbsp;&nbsp;</th><th> </th><td class="header">
        <address>Andrzej Krzemie&#324;ski &lt;akrzemi1 at gmail dot com&gt;</address>
    </td>
  </tr>
</tbody></table>



<h1>Observed a contract violation? Skip subsequent assertions!</h1>


<p> In this paper we propose a modification (on top of <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2900r12.pdf"
       title="Joshua Berne, Timur Doumler, Andrzej Krzemieński et al., &ldquo;Contracts for C++&rdquo;">[P2900R12]</a>) 
    to contract assertion evaluation 
    semantic <em>observe</em> in order to avoid undefined behavior that could 
    otherwise be introduced in certain scenarios.
    </p>


<h2><a class="sect" id="1">1.</a> Motivation</h2>


<p> Consider the following function definition.</p>

<pre>
Tool* selectTool(Tool* ta, Tool* tb)
  pre (ta != nullptr)
  pre (ta-&gt;is_configured())
  pre (tb != nullptr)
  pre (tb-&gt;is_configured())
  post (r: r != nullptr)
  post (r: r-&gt;is_configured())
{
  if (preferFirst) return ta;
  else             return tb;
}
</pre>

<p> This function has a set of preconditions. The function can execute without 
    undefined behavior (UB) even when the pointers passed are null. The only reason 
    we express strong preconditions here
    is that we want to guarantee a strong postcondition.
    </p>

<p> Now, consider the following scenario. A program that has been using this function in
    production for years and performs satisfactorily may be calling it with null pointers.
    This has never surfaced because other parts of the program do not take advantage
    of the postcondition. Next, a library author decides to introduce contract 
    annotaitons at some point, and recommends to the users that they first 
    build the program with the new (that is, all) assertions observed 
    rather than enforced. If we hit a situation where <code>ta</code> is null,
    we end up with a newly introduced UB (when evaluating predicate <code>ta-&gt;is_configured()</code>)
    that was not present in the original program.
    </p>

<p> Note that this UB does not happen when contract assertions are evaluated in <em>ignore</em> semantic
    (because the offending expression is not evaluated) or in the <em>enforce</em> semantic 
    (because we terminate before we reach the offending expression). This is a problem exlusive to the 
    <em>observe</em> semantic.
    </p>


<h2><a class="sect" id="2">2.</a> The proposal</h2>


<p> We prpose that in any of the following sequences:
    </p>
    
<ul>
  <li>caller-facing preconditions,</li>
  <li>callee-facing preconditions,</li>
  <li>caller-facing postconditions,</li>
  <li>callee-facing postconditions,</li>
  <li>assertion statements,</li>
</ul>

<p> when a given assertion is evaluated with <em>observe</em> semantics, 
    and the contract violation is observed, the subsequent assertions in the sequence
    are evaluated with <em>ignore</em> semantics (or simply not evaluated).
    </p>

<p> There is one negative consequence of this proposal. The goal of obtaining unintrusive
    feedback about contract violations in a stable program is impeded.
    Consider a different function:
    </p>
    
<pre>
void fun (int x, int y)
  pre (x != 0)
  pre (y != 0);
</pre>
    

<p> With <em>observe</em> semantics in place, the program execution could report all violations 
    of both predicates. But with this proposal, the program will never report that <code>y</code>
    is zero when <code>x</code> is zero. 
    </p>

<p> The difference between the two examples is that in the first case the two 
    predicates are <em>related</em> while in the latter they are not. We know of no way of
    discriminating the two cases, so this proposal favours avoiding UB in the former
    example, while compromising the use case using the latter example.
    </p>

    
    
    
<h2><a class="sect" id="3">3.</a> Acknowledgements</h2>


<p> Tomasz Kamiński has suggested this solution to the introduced UB problem.
    </p>

      
       
<h2><a class="sect" id="5">5.</a> References</h2>


<ul>

          
<li>[P2900R12] — Joshua Berne, Timur Doumler, Andrzej Krzemieński et al.,
    "Contracts for C++", <br>
    (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2900r12.pdf">"https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2900r12.pdf"</a>).
    </li>
    <!--
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2900r12.pdf"
       title="Joshua Berne, Timur Doumler, Andrzej Krzemieński et al., &ldquo;Contracts for C++&rdquo;">[P2900R12]</a>
    -->
 
 


</ul>



</body></html>
