Thread overview
out contract misunderstanding (was: I cannot understand problem with argument of the function)
Sep 19, 2013
mrd
Sep 19, 2013
Ivan Kazmenko
Sep 19, 2013
monarch_dodra
Sep 19, 2013
Ivan Kazmenko
Sep 19, 2013
Artur Skawina
Sep 19, 2013
mrd
September 19, 2013
(new topic because old is mired in a long and clumsy source code)

============
import std.stdio;

static ubyte func( ulong value )
out( arr )
{
    writeln( "out contract, value=", value );
}
body
{
    writeln( "body, value=", value );
    ubyte res;
    value >>= 7;
    return res;
}

void main()
{
    func( 2 );
}
============

$ ./bug
body, value=2
out contract, value=0

Why argument "value" in contract isn't equal 2 ?
September 19, 2013
On Thursday, 19 September 2013 at 01:41:15 UTC, mrd wrote:
> $ ./bug
> body, value=2
> out contract, value=0
>
> Why argument "value" in contract isn't equal 2 ?

Why should it be?  value is a mutable argument, and the out contract evaluates it at the return point, which is after it's set to 0.  It is no different than using value in the body just before the return point.

If you want to preserve the original arguments until the return point, use const and create a mutable duplicate.

Ivan Kazmenko.
September 19, 2013
On Thursday, 19 September 2013 at 06:39:09 UTC, Ivan Kazmenko wrote:
> On Thursday, 19 September 2013 at 01:41:15 UTC, mrd wrote:
>> $ ./bug
>> body, value=2
>> out contract, value=0
>>
>> Why argument "value" in contract isn't equal 2 ?
>
> Why should it be?  value is a mutable argument, and the out contract evaluates it at the return point, which is after it's set to 0.  It is no different than using value in the body just before the return point.
>
> If you want to preserve the original arguments until the return point, use const and create a mutable duplicate.
>
> Ivan Kazmenko.

I actually asked about this on the main threads:

http://forum.dlang.org/thread/gdmwjyrefhreghznbibg@forum.dlang.org

I actually disagree though: How the function is implemented should have no bearing on how the output contract should be implemented. Both should get their own copy of the args. The implementation of a function should not have to create a local duplicate just because it happens to know that it has an out contract.

This is particularly relent since (in theory), an in/out contract should appear in a function's interface, and compiled/called by client code (though that's not the case today).
September 19, 2013
On Thursday, 19 September 2013 at 06:39:09 UTC, Ivan Kazmenko wrote:
> On Thursday, 19 September 2013 at 01:41:15 UTC, mrd wrote:
>> $ ./bug
>> body, value=2
>> out contract, value=0
>>
>> Why argument "value" in contract isn't equal 2 ?
>
> Why should it be?  value is a mutable argument, and the out contract evaluates it at the return point, which is after it's set to 0.  It is no different than using value in the body just before the return point.

Why? it seems the documentation does not say anything about it.
Using variables values from another {} block is confusing.
September 19, 2013
On Thursday, 19 September 2013 at 07:45:44 UTC, monarch_dodra wrote:
> On Thursday, 19 September 2013 at 06:39:09 UTC, Ivan Kazmenko wrote:
>> On Thursday, 19 September 2013 at 01:41:15 UTC, mrd wrote:
>>> Why argument "value" in contract isn't equal 2 ?
>> Why should it be?  <snip>
> I actually disagree though: How the function is implemented should have no bearing on how the output contract should be implemented. Both should get their own copy of the args. The implementation of a function should not have to create a local duplicate just because it happens to know that it has an out contract.
>
> This is particularly relent since (in theory), an in/out contract should appear in a function's interface, and compiled/called by client code (though that's not the case today).

That doesn't seem to be possible in every case.  For example, what if an argument is a class with copy constructor disabled?

I'm not claiming that the current behavior is the best one.  I just don't get a coherent picture of how it could be defined otherwise.  And the current definition seems to follow the principle of least surprise for me.

Ivan Kazmenko.
September 19, 2013
On 09/19/13 20:01, Ivan Kazmenko wrote:
> On Thursday, 19 September 2013 at 07:45:44 UTC, monarch_dodra wrote:
>> On Thursday, 19 September 2013 at 06:39:09 UTC, Ivan Kazmenko wrote:
>>> On Thursday, 19 September 2013 at 01:41:15 UTC, mrd wrote:
>>>> Why argument "value" in contract isn't equal 2 ?
>>> Why should it be?  <snip>
>> I actually disagree though: How the function is implemented should have no bearing on how the output contract should be implemented. Both should get their own copy of the args. The implementation of a function should not have to create a local duplicate just because it happens to know that it has an out contract.
>>
>> This is particularly relent since (in theory), an in/out contract should appear in a function's interface, and compiled/called by client code (though that's not the case today).
> 
> That doesn't seem to be possible in every case.  For example, what if an argument is a class with copy constructor disabled?

In general, the problem is with accessing the argument at all, it could indeed be uncopyable, but it could also be invalid /after/ the body of the function is executed. Eg

   void f(ref S s) out { assert(s.x==42); } body { free(&s); }

Anything that either invalidates or moves ownership can easily result in invalid accesses. Variations on this could use pointers, classes, s/free/send/, refcounts etc (and having to always clear every stale ref isn't a practical solution).

> I'm not claiming that the current behavior is the best one.  I just don't get a coherent picture of how it could be defined otherwise.  And the current definition seems to follow the principle of least surprise for me.

out-contracts shouldn't have access to the input args by default; that is something that should be explicitly requested. Some syntax sugar, for the cases when it actually is needed, could be nice, yes.

But it's not how D currently defines out contracts, so that would be a larger change than just fixing the leak (which isn't a big problem in itself, the implications of speccing it like that would be).

artur