www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Crash in out contract in interface

reply =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
Hi,

This is an odd one. Consider the following code:

 interface I
 {
     void foo()
     out { assert(bar()); }
     bool bar();
 }

 class C : I
 {
     void foo() {}
     bool bar() { return true; }
 }

 void main()
 {
     C c = new C();
     c.foo();
 }

This will crash and burn when run:
 object.Error: Access Violation
 ----------------
 40DB64
 40D9DB
 402050
 402074
 4026F3
 4022EF
 4127B5
 ----------------

I assume this is a bug, but has anyone encountered this before or have any idea why exactly it happens when calling other interface methods in an interface method's out contract? (It seems to work fine in the in contract.) - Alex
Aug 24 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/24/2011 03:13 PM, Alex Rønne Petersen wrote:
 Hi,

 This is an odd one. Consider the following code:

 interface I
 {
 void foo()
 out { assert(bar()); }
 bool bar();
 }

 class C : I
 {
 void foo() {}
 bool bar() { return true; }
 }

 void main()
 {
 C c = new C();
 c.foo();
 }

This will crash and burn when run:
 object.Error: Access Violation
 ----------------
 40DB64
 40D9DB
 402050
 402074
 4026F3
 4022EF
 4127B5
 ----------------

I assume this is a bug, but has anyone encountered this before or have any idea why exactly it happens when calling other interface methods in an interface method's out contract? (It seems to work fine in the in contract.) - Alex

I think it actually makes a lot of sense. I.foo's out contract assumes an I this reference, but C.foo passes a C this reference without adjustment. What I don't quite get yet is what is the matter with in contracts on interface member functions. Not only do they not crash, apparently they are not even executed. Have you already filed a bug report?
Aug 24 2011
next sibling parent =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 24-08-2011 15:35, Timon Gehr wrote:
 On 08/24/2011 03:13 PM, Alex Rønne Petersen wrote:
 Hi,

 This is an odd one. Consider the following code:

 interface I
 {
 void foo()
 out { assert(bar()); }
 bool bar();
 }

 class C : I
 {
 void foo() {}
 bool bar() { return true; }
 }

 void main()
 {
 C c = new C();
 c.foo();
 }

This will crash and burn when run:
 object.Error: Access Violation
 ----------------
 40DB64
 40D9DB
 402050
 402074
 4026F3
 4022EF
 4127B5
 ----------------

I assume this is a bug, but has anyone encountered this before or have any idea why exactly it happens when calling other interface methods in an interface method's out contract? (It seems to work fine in the in contract.) - Alex

I think it actually makes a lot of sense. I.foo's out contract assumes an I this reference, but C.foo passes a C this reference without adjustment. What I don't quite get yet is what is the matter with in contracts on interface member functions. Not only do they not crash, apparently they are not even executed. Have you already filed a bug report?

Not yet. I figured I'd ask here first. - Alex
Aug 24 2011
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/24/2011 03:35 PM, Timon Gehr wrote:
 On 08/24/2011 03:13 PM, Alex Rønne Petersen wrote:
 Hi,

 This is an odd one. Consider the following code:

 interface I
 {
 void foo()
 out { assert(bar()); }
 bool bar();
 }

 class C : I
 {
 void foo() {}
 bool bar() { return true; }
 }

 void main()
 {
 C c = new C();
 c.foo();
 }

This will crash and burn when run:
 object.Error: Access Violation
 ----------------
 40DB64
 40D9DB
 402050
 402074
 4026F3
 4022EF
 4127B5
 ----------------

I assume this is a bug, but has anyone encountered this before or have any idea why exactly it happens when calling other interface methods in an interface method's out contract? (It seems to work fine in the in contract.) - Alex

I think it actually makes a lot of sense. I.foo's out contract assumes an I this reference, but C.foo passes a C this reference without adjustment. What I don't quite get yet is what is the matter with in contracts on interface member functions. Not only do they not crash, apparently they are not even executed. Have you already filed a bug report?

This seems to confirm I was on the right path: import std.stdio; interface I { void foo() out { writeln(typeid(this));} bool bar(); final void qux(){ writeln(typeid(this)); } } class C : I { void foo() { } bool bar() { return false; } } void main() { C c = new C(); c.qux(); // "modulename.I" c.foo(); // "TypeInfo_Class", not sure why it is not modulename.C. } So, basically interfaces are the only place in D?/DMD where you can even specify contracts without a function body and there they don't work. I think the bug is not the only problem, actual contracts should /always/ be part of the function declaration and not require an implementation to work. Everything else degrades contracts to simple syntactic sugar for assertions.
Aug 24 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 8/24/11 6:58 AM, Timon Gehr wrote:
 So, basically interfaces are the only place in D?/DMD where you can even
 specify contracts without a function body and there they don't work. I
 think the bug is not the only problem, actual contracts should /always/
 be part of the function declaration and not require an implementation to
 work. Everything else degrades contracts to simple syntactic sugar for
 assertions.

That plus interplay with inheritance. Andrei
Aug 24 2011
next sibling parent reply =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 24-08-2011 16:47, Andrei Alexandrescu wrote:
 On 8/24/11 6:58 AM, Timon Gehr wrote:
 So, basically interfaces are the only place in D?/DMD where you can even
 specify contracts without a function body and there they don't work. I
 think the bug is not the only problem, actual contracts should /always/
 be part of the function declaration and not require an implementation to
 work. Everything else degrades contracts to simple syntactic sugar for
 assertions.

That plus interplay with inheritance. Andrei

Have you seen how Microsoft's Code Contracts deals with inheritance? It's described in the documentation at this page: http://msdn.microsoft.com/en-us/devlabs/dd491992 - Alex
Aug 24 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 8/24/11 9:39 AM, Alex Rønne Petersen wrote:
 On 24-08-2011 16:47, Andrei Alexandrescu wrote:
 On 8/24/11 6:58 AM, Timon Gehr wrote:
 So, basically interfaces are the only place in D?/DMD where you can even
 specify contracts without a function body and there they don't work. I
 think the bug is not the only problem, actual contracts should /always/
 be part of the function declaration and not require an implementation to
 work. Everything else degrades contracts to simple syntactic sugar for
 assertions.

That plus interplay with inheritance. Andrei

Have you seen how Microsoft's Code Contracts deals with inheritance? It's described in the documentation at this page: http://msdn.microsoft.com/en-us/devlabs/dd491992 - Alex

I assume you refer to the PDF documentation linked from that page, http://download.microsoft.com/download/C/2/7/C2715F76-F56C-4D37-9231-EF807 B7EC13/userdoc.pdf. Anyhow, the handling is fairly standard, so what is your point? Andrei
Aug 24 2011
parent =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 24-08-2011 19:52, Andrei Alexandrescu wrote:
 On 8/24/11 9:39 AM, Alex Rønne Petersen wrote:
 On 24-08-2011 16:47, Andrei Alexandrescu wrote:
 On 8/24/11 6:58 AM, Timon Gehr wrote:
 So, basically interfaces are the only place in D?/DMD where you can
 even
 specify contracts without a function body and there they don't work. I
 think the bug is not the only problem, actual contracts should /always/
 be part of the function declaration and not require an
 implementation to
 work. Everything else degrades contracts to simple syntactic sugar for
 assertions.

That plus interplay with inheritance. Andrei

Have you seen how Microsoft's Code Contracts deals with inheritance? It's described in the documentation at this page: http://msdn.microsoft.com/en-us/devlabs/dd491992 - Alex

I assume you refer to the PDF documentation linked from that page, http://download.microsoft.com/download/C/2/7/C2715F76-F56C-4D37-9231-EF8076B7EC13/userdoc.pdf. Anyhow, the handling is fairly standard, so what is your point? Andrei

Oh, I was simply suggesting that it might be a good way for D to do contracts with inheritance, in case there were still design choices to be made in this area. - Alex
Aug 29 2011
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/24/2011 04:47 PM, Andrei Alexandrescu wrote:
 On 8/24/11 6:58 AM, Timon Gehr wrote:
 So, basically interfaces are the only place in D?/DMD where you can even
 specify contracts without a function body and there they don't work. I
 think the bug is not the only problem, actual contracts should /always/
 be part of the function declaration and not require an implementation to
 work. Everything else degrades contracts to simple syntactic sugar for
 assertions.

That plus interplay with inheritance. Andrei

Well, yes, that is true. Where one can add contracts, they will be inherited. But inheritance is actually where D's current contract programming model is weakest: It should be possible to use inheritance to create classes that move gradually from unimplemented, but specified to implemented and extended. The fact that unimplemented methods in an abstract class cannot define contracts is an unforgivable left-out, because that is where contracts are most useful: for the specification of what all implementations of the method are allowed to assume and must guarantee. Contracts are declarative: "If you guarantee this, I will guarantee that." Contracts and implementation are two completely orthogonal concepts, and there is no reason to couple them in any way. Not allowing contracts without implementation is like telling a customer "You are not allowed to specify your needs unless we have already written code to satisfy them." Do you agree that this will have to be fixed eventually, when all the more important features are fully working? PS: I realize that there are workarounds: - Just provide an empty body. But then you lose the enforcement for implementations of that method in heirs of the abstract class, and every one of them will have to specify pointless "override"'s that make the code less self-documenting. Also, if there is a non-trivial postcondition, an empty implementation is just a wrong implementation. So this is no solution. - For every abstract class, write an interface that specifies all the contracts for all the unimplemented methods, and let the class inherit from it. Considering that this is the most common use case in a sanely designed contract programming project, that is not an optimal design at all. (and if you do this, your program will currently crash) - Never use abstract classes but only the NVI idiom. Either you declare each method twice, once final with contracts to wrap the other, or go to some Eiffel users and let them have a good laugh by telling them that in your favorite language, 'deferred' classes and contracts cannot be used together, if you don't 'freeze' all implemented 'features', and similar stuff. :o)
Aug 24 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 8/24/11 9:45 AM, Timon Gehr wrote:
 On 08/24/2011 04:47 PM, Andrei Alexandrescu wrote:
 On 8/24/11 6:58 AM, Timon Gehr wrote:
 So, basically interfaces are the only place in D?/DMD where you can even
 specify contracts without a function body and there they don't work. I
 think the bug is not the only problem, actual contracts should /always/
 be part of the function declaration and not require an implementation to
 work. Everything else degrades contracts to simple syntactic sugar for
 assertions.

That plus interplay with inheritance. Andrei

Well, yes, that is true. Where one can add contracts, they will be inherited. But inheritance is actually where D's current contract programming model is weakest: It should be possible to use inheritance to create classes that move gradually from unimplemented, but specified to implemented and extended. The fact that unimplemented methods in an abstract class cannot define contracts is an unforgivable left-out, because that is where contracts are most useful: for the specification of what all implementations of the method are allowed to assume and must guarantee.

Indeed. That should be filed as a bug. But you are exaggerating a bit because as you yourself note there are obvious workarounds.
 Contracts are declarative:
 "If you guarantee this, I will guarantee that."

 Contracts and implementation are two completely orthogonal concepts,
 and there is no reason to couple them in any way. Not allowing
 contracts without implementation is like telling a customer "You are
 not allowed to specify your needs unless we have already written code
 to satisfy them."

 Do you agree that this will have to be fixed eventually, when all the
 more important features are fully working?

You should know that we introduced contracts in interfaces in spite of considerable implementation difficulties. So yes, we do consider implementation-less contracts important. Andrei
Aug 24 2011
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/24/2011 07:57 PM, Andrei Alexandrescu wrote:
 On 8/24/11 9:45 AM, Timon Gehr wrote:
 On 08/24/2011 04:47 PM, Andrei Alexandrescu wrote:
 On 8/24/11 6:58 AM, Timon Gehr wrote:
 So, basically interfaces are the only place in D?/DMD where you can
 even
 specify contracts without a function body and there they don't work. I
 think the bug is not the only problem, actual contracts should /always/
 be part of the function declaration and not require an
 implementation to
 work. Everything else degrades contracts to simple syntactic sugar for
 assertions.

That plus interplay with inheritance. Andrei

Well, yes, that is true. Where one can add contracts, they will be inherited. But inheritance is actually where D's current contract programming model is weakest: It should be possible to use inheritance to create classes that move gradually from unimplemented, but specified to implemented and extended. The fact that unimplemented methods in an abstract class cannot define contracts is an unforgivable left-out, because that is where contracts are most useful: for the specification of what all implementations of the method are allowed to assume and must guarantee.

Indeed. That should be filed as a bug. But you are exaggerating a bit because as you yourself note there are obvious workarounds.

Done: http://d.puremagic.com/issues/show_bug.cgi?id=6549 Note that none of the workarounds I could think of does not invade the inheritance interface. When I am talking about so-called 'issues' the D programming language has, I always mean 'issues from a highly purist and perfectionist standpoint'. If the goal is to have absolutely perfect contract programming support in D, then I think my statements are not exaggerated. But if it helps, I can choose my words more careful next time.
 Contracts are declarative:
 "If you guarantee this, I will guarantee that."

 Contracts and implementation are two completely orthogonal concepts,
 and there is no reason to couple them in any way. Not allowing
 contracts without implementation is like telling a customer "You are
 not allowed to specify your needs unless we have already written code
 to satisfy them."

 Do you agree that this will have to be fixed eventually, when all the
 more important features are fully working?

You should know that we introduced contracts in interfaces in spite of considerable implementation difficulties. So yes, we do consider implementation-less contracts important.

Great. I appreciate that. I blindly assume that implementation-less contracts in classes will be simpler to implement than contracts in interfaces.
Aug 24 2011