strange behavior of by-value function arguments in postcondition

bauss jj_1337 at live.dk
Tue Aug 31 11:30:16 UTC 2021


On Tuesday, 31 August 2021 at 10:43:41 UTC, Andrzej K. wrote:
> Have a look at the following short example:
>
> https://d.godbolt.org/z/1KoofEx5Y
>
>
> We have a function that takes arguments by value and has a 
> postcondition that refers to these arguments:
>
> ```D
> int select(int lo, int hi)
>   in (lo <= hi)
>   out (r; lo <= r && r <= hi)
> {
>   int ans = lo;
>   lo = hi; // why not
>   return ans;
> }
> ```
>
> I would intuitively assume that the contract of such a function 
> is: "I will not modify your objects, and I will select a number 
> from the range that your objects indicate." This expectation of 
> mine can be reflected by the following assertions:
>
> ```D
> void main()
> {
>     int lo = 1;
>     int hi = 4;
>     int i = select(lo, hi);
>     assert(lo == 1);
>     assert(hi == 4);
>     assert(i >= 1 && i <= 4);
> }
> ```
>
> The fact that function `select()` modifies its copy of the 
> argument, should not be of interest to the caller: it is an 
> implementation detail of the function. And all the assertions 
> in function `main()` are satisfied. However, the fact that 
> postcondition observes the copies of user objects makes the 
> postcondition fail.
>
> I realize that this effect is consistent with the mechanics of 
> the language. But it seems that the mechanics of the language 
> render the postconditions somewhat counterintuitive. The 
> postcondition should reflect the contract: it should describe 
> something that the caller can also see and understand: not the 
> state of internal copies of user input.
>
> Is this not a design bug?

To me it makes perfect sense as the function would probably 
translated to something like this:

int select(int lo, int hi)
{
   // in
   assert(lo <= hi);

   // body
   int ans = lo;
   lo = hi;

   // out
   int r = ans;
   assert(lo <= r && r <= hi);

   return r;
}


More information about the Digitalmars-d mailing list