[Issue 6856] Preconditions are not inherited

2012-05-03 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856


timon.g...@gmx.ch changed:

   What|Removed |Added

 CC||adam.chrapkow...@gmail.com


--- Comment #27 from timon.g...@gmx.ch 2012-05-03 14:32:27 PDT ---
*** Issue 8027 has been marked as a duplicate of this issue. ***

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


[Issue 6856] Preconditions are not inherited

2012-02-27 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #24 from Don clugd...@yahoo.com.au 2012-02-27 22:14:03 PST ---
(In reply to comment #23)
 (In reply to comment #22)
  What this means in practice is that in contracts must be BEFORE the vtable
  lookup, rather than being in the body of the function.
 
 Yes, that is issue 6857.

OK, then this issue is quite simple.
All that seems to be required is, to define no in() contract to mean use
default precondition. So that if a derived class has no in(), instead of
getting

base.in() || true

(which means that the precondition gets stripped away) it gets

base.in() || false.

(which means it uses the precondition from the base class). As now, an explicit
in{} strips the precondition away.
And nothing else needs to change.

Works?

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


[Issue 6856] Preconditions are not inherited

2012-02-27 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #25 from timon.g...@gmx.ch 2012-02-27 23:28:16 PST ---
Yes, I think that works. The issue can be resolved by making the default 'in'
contract empty if the method is introduced without overriding another and
'assert(false)' if the method overrides another.

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


[Issue 6856] Preconditions are not inherited

2012-02-26 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856


deadalnix deadal...@gmail.com changed:

   What|Removed |Added

 CC||deadal...@gmail.com


--- Comment #14 from deadalnix deadal...@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: ---


[Issue 6856] Preconditions are not inherited

2012-02-26 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #15 from timon.g...@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: ---


[Issue 6856] Preconditions are not inherited

2012-02-26 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #16 from deadalnix deadal...@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: ---


[Issue 6856] Preconditions are not inherited

2012-02-26 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #17 from timon.g...@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: ---


[Issue 6856] Preconditions are not inherited

2012-02-26 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #18 from deadalnix deadal...@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: ---


[Issue 6856] Preconditions are not inherited

2012-02-26 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #19 from Stewart Gordon s...@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: ---


[Issue 6856] Preconditions are not inherited

2012-02-26 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #20 from timon.g...@gmx.ch 2012-02-26 10:30:17 PST ---
(In reply to comment #19)
 (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. 

I look at it in a pragmatic way. Have you ever used the feature in any
language?

 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.
 

By symmetry, the view would have to be taken that the out contract supplements
the return type. Do you see how that is problematic?

Whatever reason for the current behavior there might be come up with when
thinking hard about it: The current behavior of DMD is not useful, and I refuse
to believe that it is by design. I am not aware of any language that specifies
such non-useful semantics for their contract inheritance.

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


[Issue 6856] Preconditions are not inherited

2012-02-26 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856


Jesse Phillips jesse.k.phillip...@gmail.com changed:

   What|Removed |Added

 CC||jesse.k.phillip...@gmail.co
   ||m


--- Comment #21 from Jesse Phillips jesse.k.phillip...@gmail.com 2012-02-26 
19:34:51 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.

If I didn't supply an 'in' to the derived class function, I would expect not
abiding by the base class contract to be an error. So I agree that an explicate
foo() in{} should be used and that foo() in { assert(0); } looks like an ugly
workaround, and would prefer not to restate the inherited class contract.

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


[Issue 6856] Preconditions are not inherited

2011-11-03 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #13 from Leandro Lucarella llu...@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: ---


[Issue 6856] Preconditions are not inherited

2011-11-02 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856


Don clugd...@yahoo.com.au changed:

   What|Removed |Added

 CC||clugd...@yahoo.com.au


--- Comment #9 from Don clugd...@yahoo.com.au 2011-11-02 01:30:27 PDT ---
(In reply to comment #8)
 (In reply to comment #2)
  Shouldn't Y y print Y.f() if Y can loose the in contract?
  Shouldn't X z and Y z print *something* (probably X.f() and Y.f()
  respectively)?
 
 Only one of the contracts needs to pass for the overall contract to pass.  So
 once it's tried one and found that it's passed, it doesn't need to try the
 others.
 
 When you have a Y, it first tries X's in contract.  This passes, so it doesn't
 need to check Y's as well.  Of course, an implementation could just as well
 check Y's contract first and then fall back to X's if that fails.
 
 But because Z's in contract is empty, the compiler just optimises away the
 whole contract checking.

I'm a little confused by the relationship between this bug and bug 6857.
If you accept 6857, then if you call a function f() from a base class B, only
the precondition of the base class should matter. Although one derived class
C.f() may accept a weaker precondition, the caller doesn't actually know it had
a C, so it's making an unwarranted assumption.

So, if you accept that, then contracts in derived classes don't matter unless
they are called directly.

That's really odd, because you have a single function which has two different
semantic guarantees depending on who is calling it.
Following this through, I don't see the need for explicit widening of
preconditions at all. If we didn't have the feature, and you needed it (which I
believe happens very rarely), you could just create a separate function g() for
the direct calls, and give _it_ the weaker contract. The derived function f()
can just call g(). If you need to rely on the weaker contract, call g() instead
of f(). Easy to implement, easy to understand.

This explicit widening of preconditions of virtual functions seems to be a
really niche feature.

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


[Issue 6856] Preconditions are not inherited

2011-11-02 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #10 from Leandro Lucarella llu...@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: ---


[Issue 6856] Preconditions are not inherited

2011-11-02 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #11 from Leandro Lucarella llu...@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: ---


[Issue 6856] Preconditions are not inherited

2011-11-02 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #12 from Don clugd...@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: ---


[Issue 6856] Preconditions are not inherited

2011-11-01 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856


Leandro Lucarella llu...@gmail.com changed:

   What|Removed |Added

 CC||llu...@gmail.com
Version|D2  |D1  D2


--- Comment #2 from Leandro Lucarella llu...@gmail.com 2011-11-01 05:25:05 
PDT ---
What about this:

extern (C) int printf(char* s, ...);

class X
{
void f()
in { printf(\tX.f() in\n); }
body {}
}

class Y : X
{
override void f()
in { printf(\tY.f() in\n); }
body {}
}

class Z : Y
{
override void f()
body {}
}

void main()
{
printf(X x\n);
X xx = new X;
xx.f();
printf(\t---\n);

printf(X y\n);
X xy = new Y;
xy.f();
printf(\t---\n);

printf(X z\n);
X xz = new Z;
xz.f();
printf(\t---\n);

printf(\n);
printf(Y y\n);
Y yy = new Y;
yy.f();
printf(\t---\n);

printf(Y z\n);
Y yz = new Z;
yz.f();
printf(\t---\n);

printf(\n);
printf(Z z\n);
Z z = new Z;
z.f();
printf(\t---\n);
}


It prints:

X x
X.f() in
---
X y
X.f() in
---
X z
---

Y y
X.f() in
---
Y z
---

Z z
---


Shouldn't Y y print Y.f() if Y can loose the in contract?
Shouldn't X z and Y z print *something* (probably X.f() and Y.f()
respectively)?

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


[Issue 6856] Preconditions are not inherited

2011-11-01 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #3 from Leandro Lucarella llu...@gmail.com 2011-11-01 05:27:32 
PDT ---
BTW, that was DMD 1.071.

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


[Issue 6856] Preconditions are not inherited

2011-11-01 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #4 from Leandro Lucarella llu...@gmail.com 2011-11-01 05:46:43 
PDT ---
BTW, in contracts seems to be very ill defined, because overriding a method
with an in contract without specifying an in contract should inherit the
contract from the base class/interface, not remove the contract completely. You
have to repeat the contract from the base class manually, that sucks. There
should be some syntax to remove the contract instead, maybe something like:

void f()
in delete
body
{
  // ...
}

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


[Issue 6856] Preconditions are not inherited

2011-11-01 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #5 from timon.g...@gmx.ch 2011-11-01 05:57:01 PDT ---
@Leandro: Your first example is okay. The precondition test shortcuts. It is
more or less equivalent to passes(X_foo_in) || passes(Y_foo_in). If
passes(X_foo_in), then the second part does not have to be evaluated, ergo it
never prints Y.f() in.

The fact that in order to just inherit an in contract it is necessary to add an
in{assert(0);} contract is hopefully just an oversight and not by design.

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


[Issue 6856] Preconditions are not inherited

2011-11-01 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #6 from timon.g...@gmx.ch 2011-11-01 05:59:14 PDT ---
(In reply to comment #4)
 BTW, in contracts seems to be very ill defined, because overriding a method
 with an in contract without specifying an in contract should inherit the
 contract from the base class/interface, not remove the contract completely. 
 You
 have to repeat the contract from the base class manually, that sucks. There
 should be some syntax to remove the contract instead, maybe something like:
 
 void f()
 in delete
 body
 {
   // ...
 }

I think it should just look like this:

override void f()
in{}body{
  // ...
}

If no explicit contract is added, it should be inherited.

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


[Issue 6856] Preconditions are not inherited

2011-11-01 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #7 from Leandro Lucarella llu...@gmail.com 2011-11-01 09:50:56 
PDT ---
OK, then the docs should be more clear I think, is really hard to infer this
behavior from the docs (unless someone explains it better :).

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


[Issue 6856] Preconditions are not inherited

2011-11-01 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856



--- Comment #8 from Stewart Gordon s...@iname.com 2011-11-01 10:06:36 PDT ---
(In reply to comment #2)
 Shouldn't Y y print Y.f() if Y can loose the in contract?
 Shouldn't X z and Y z print *something* (probably X.f() and Y.f()
 respectively)?

Only one of the contracts needs to pass for the overall contract to pass.  So
once it's tried one and found that it's passed, it doesn't need to try the
others.

When you have a Y, it first tries X's in contract.  This passes, so it doesn't
need to check Y's as well.  Of course, an implementation could just as well
check Y's contract first and then fall back to X's if that fails.

But because Z's in contract is empty, the compiler just optimises away the
whole contract checking.

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


[Issue 6856] Preconditions are not inherited

2011-10-29 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6856


Stewart Gordon s...@iname.com changed:

   What|Removed |Added

 CC||s...@iname.com


--- Comment #1 from Stewart Gordon s...@iname.com 2011-10-29 18:20:20 PDT ---
http://www.digitalmars.com/d/1.0/dbc.html
If a function in a derived class overrides a function in its super class, then
only one of the in contracts of the function and its base functions must be
satisfied. Overriding functions then becomes a process of loosening the in
contracts.

A function without an in contract means that any values of the function
parameters are allowed.

On an override, the semantics of an in contract are to _add_ to what is a legal
call of the method.  And the absence of an in contract in a function definition
is really syntactic sugar for an empty in contract.

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