November 02, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #10 from Leandro Lucarella <llucax@gmail.com> 2011-11-02 07:11:42 PDT ---
(In reply to comment #9)
> This explicit widening of preconditions of virtual functions seems to be a really niche feature.

I think it does makes some sense to be like this. You can see it as adding an extra method to a derived class, or class implementing an interface. The derived class adding a new method() still satisfies the interface, in the same sense an overriden method accepting wider preconditions still satisfies the original precondition, and the interface.

The problem for me is:

1) The docs are not very clear about that. I didn't understood they worked like this until now, that some change in the compiler triggered an error on a "in" contract in Tango. I don't think I'm the only one misunderstanding contracts, as when I took a look at the code pre-conditions was wrongly used all over it.

2) There seem to be bugs in the implementation. For example in this Tango bug report: http://www.dsource.org/projects/tango/ticket/2067, the sync() method is OK to trigger the error because it comes from an interface with no preconditions, but the close() error seems to be wrong, as the parent class also has a precondition on that method. I didn't have the time to try to come up with a minimal testcase yet, sorry.

Also, see this example:
extern (C) int printf(char* s, ...);

class X
{
    void f(bool failx = false, bool faily = false)
    in { printf("\tX.f() in: assert(%d)\n", !failx); assert(!failx); }
    body {}
}

class Y : X
{
    override void f(bool failx = false, bool faily = false)
    in { printf("\tY.f() in: assert(%d)\n", !faily); assert(!faily); }
    body {}
}

class Z : Y
{
    override void f(bool failx = false, bool faily = false)
    in { printf("\tZ.f() in: assert(0)\n");  assert(false); }
    body {}
}

void main()
{
    printf("--------------------\n");
    printf("Z z\n");
    Z z = new Z;
    z.f(true, true);
    printf("\t---\n");
}

This is the output:
--------------------
Z z
    Y.f() in: assert(1)
    ---

Is there any good reason why suddenly faily gets set to false when true was passed? If this is confirmed as a bug I'll create another ticket.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
November 02, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #11 from Leandro Lucarella <llucax@gmail.com> 2011-11-02 07:13:07 PDT ---
Oh, and I think it will also make more sense to first check the subclass pre-condition (as it might be the wider one, and the one with more chances to pass) instead of the parent class, which is the more restrictive.

I don't know if that's too hard to implement, and only a detail :)

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
November 03, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #12 from Don <clugdbug@yahoo.com.au> 2011-11-02 17:37:44 PDT ---
(In reply to comment #10)
> (In reply to comment #9)
> > This explicit widening of preconditions of virtual functions seems to be a really niche feature.
> 
> I think it does makes some sense to be like this. You can see it as adding an extra method to a derived class, or class implementing an interface.

Yes. But in those cases you mention, the syntax for accessing the base functionality is different to the derived functionality. But here we have something different:

    Derived c;
    Base b = c;
    c.foo(7); // OK
    b.foo(7); // fail -- precondition is not widened

Same function body gets used in both calls, BUT different contracts need to get called.

> The
> derived class adding a new method() still satisfies the interface, in the same
> sense an overriden method accepting wider preconditions still satisfies the
> original precondition, and the interface.

Yes, it does, but why is that desirable? When do you actually want that? Only in niche cases, I think.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
November 03, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #13 from Leandro Lucarella <llucax@gmail.com> 2011-11-03 07:26:39 PDT ---
(In reply to comment #12)
> (In reply to comment #10)
> > (In reply to comment #9)
> > > This explicit widening of preconditions of virtual functions seems to be a really niche feature.
> > 
> > I think it does makes some sense to be like this. You can see it as adding an extra method to a derived class, or class implementing an interface.
> 
> Yes. But in those cases you mention, the syntax for accessing the base functionality is different to the derived functionality. But here we have something different:
> 
>     Derived c;
>     Base b = c;
>     c.foo(7); // OK
>     b.foo(7); // fail -- precondition is not widened
> 
> Same function body gets used in both calls, BUT different contracts need to get called.

I still don't see how that's wrong. I can understand it could be awful to implement. And I can even agree that it doesn't worth the trouble. But the code it self makes sense to me.

> > The
> > derived class adding a new method() still satisfies the interface, in the same
> > sense an overriden method accepting wider preconditions still satisfies the
> > original precondition, and the interface.
> 
> Yes, it does, but why is that desirable? When do you actually want that? Only in niche cases, I think.

Yes, that's probably true. But if it's something easy to do, I see the sense on having the feature. If it's extremely hard I agree it might not worth it.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 26, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=6856


deadalnix <deadalnix@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |deadalnix@gmail.com


--- Comment #14 from deadalnix <deadalnix@gmail.com> 2012-02-26 04:35:23 PST ---
A's in must be executed only if B's in fails. in constract lossen themselves with override.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 26, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #15 from timon.gehr@gmx.ch 2012-02-26 05:11:34 PST ---
There is no "B's in". That is the point. The bug is that an implicit 'in' contract that always passes is added to B.foo.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 26, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #16 from deadalnix <deadalnix@gmail.com> 2012-02-26 07:43:52 PST ---
(In reply to comment #15)
> There is no "B's in". That is the point. The bug is that an implicit 'in' contract that always passes is added to B.foo.

Yes that is the point. As no contract has been specified, it is assumed that this function can accept anything. And so the implicit in contract alway succeed, so A's contract never get executed.

Stewart Gordon already explained that and he is right.

However, Don's proposal make sense (defining how contract is executed at callee's place instead of caller's place).

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 26, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #17 from timon.gehr@gmx.ch 2012-02-26 08:30:09 PST ---
(In reply to comment #16)
> (In reply to comment #15)
> > There is no "B's in". That is the point. The bug is that an implicit 'in' contract that always passes is added to B.foo.
> 
> Yes that is the point. As no contract has been specified,

Wrong. The super class specifies a contract. This contract must be inherited.

> it is assumed that this function can accept anything.

That assumption is bogus, because this is almost never the case. It makes contract programming basically unusable. Such a strong weakening of the 'in' contract should not be the default.

> And so the implicit in contract alway
> succeed, so A's contract never get executed.
> 
> Stewart Gordon already explained that and

I understand all of this, and the fact that it works that way is a bug.

> he is right.
> 

He is right in that the implementation works that way. It shouldn't.

> However, Don's proposal make sense (defining how contract is executed at callee's place instead of caller's place).

Don's proposal is to remove 'in' contract widening completely. That does not make a lot of sense to me.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 26, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #18 from deadalnix <deadalnix@gmail.com> 2012-02-26 08:46:45 PST ---
(In reply to comment #17)
> Don's proposal is to remove 'in' contract widening completely. That does not make a lot of sense to me.

Don's proposal is similar to what you reported here as issue 6857 , which make a lot of sense.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 26, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #19 from Stewart Gordon <smjg@iname.com> 2012-02-26 09:15:32 PST ---
(In reply to comment #17)
> That assumption is bogus, because this is almost never the case. It makes contract programming basically unusable.  Such a strong weakening of the 'in' contract should not be the default.

It depends on how you look at it.  A function can, by default, accept any arguments of the types specified.  I think the view taken is that the in contract supplements the parameter list, and the absence of an in contract with a given parameter list denotes an absence of further restrictions on what may be passed into the function.

> Don's proposal is to remove 'in' contract widening completely. That does not make a lot of sense to me.

Indeed, it does seem that Don doesn't like contravariance.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------