May 03, 2012 [Issue 6857] Precondition contract checks should be statically bound. | ||||
---|---|---|---|---|
| ||||
Posted in reply to timon.gehr@gmx.ch | http://d.puremagic.com/issues/show_bug.cgi?id=6857 --- Comment #12 from deadalnix <deadalnix@gmail.com> 2012-05-03 01:43:42 PDT --- (In reply to comment #11) > >The current specification is flawed. It have nothing to do with how inheritance work (and I could assure you I know what I'm talking about, and I'm also pretty sure Timon knows also). > > Mistakes happen to the best of us. In this case the specification is correct and the bug report is in error. Derived classes may require less and provide more, which in contract lingo translates into weaker "in" contracts and stronger "out" contracts. This is not a matter in which reasonable people may disagree and not a matter of opinion. I think you misunderstood what we are talking about here, as Walter is. Nobody here discussed teh fact that in contract shouldn't become weaker when inherited. This is, indeed, what corect OO design is. What is discussed here is, with all details. class A { void foo() in { ... } body { ... } } class B : A { override void foo() in { ... } body { ... } } then, let's consider : fizbuzzA(A a) { a.foo(); // A.foo's in contract is valid } fizzbuzzB(B b) { b.foo(); // (A.foo OR B.foo)'s in contract is valid } The point is that B.foo's in contract loosen A.foo's in contract. And fizzbuzzA have no knowledge of the fact that a subclass of A's instance can be passed. So, if fizzbuzzA use foo with parameter that validate A.foo's in contract, but not B.foo's in contract, it is an error. fizzbuzzA have no knowledge of the runtime type of a, so shouldn't pass argument to foo that is invalid according to A.foo's in contract. If it does, it means that fizzbuzzA is bugguy, or does know about that fact that a isn't of type A, which is exactly what we DON'T want when doing OOP. It is Liskov substitution principle, any object of type B can be substituted to an object of type A without the code using the object knowing about it. It is probably the most important thing in OOP. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
May 03, 2012 [Issue 6857] Precondition contract checks should be statically bound. | ||||
---|---|---|---|---|
| ||||
Posted in reply to timon.gehr@gmx.ch | http://d.puremagic.com/issues/show_bug.cgi?id=6857 --- Comment #13 from Andrei Alexandrescu <andrei@metalanguage.com> 2012-05-03 07:05:18 PDT --- I apologize but I still think the confusion goes the other way. A good way to arbiter this is to peruse the literature on the subject, as Walter suggested. If going through a book has too much overhead, online articles and presentations should work, too. I can't afford to do much more explaining than essentially reciting material that's out there. For example I'd recommend this: http://www.cs.ucsb.edu/~bultan/courses/272-F08/lectures/Contract.ppt. Slides 19 and 20 should clarify the matter. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
May 03, 2012 [Issue 6857] Precondition contract checks should be statically bound. | ||||
---|---|---|---|---|
| ||||
Posted in reply to timon.gehr@gmx.ch | http://d.puremagic.com/issues/show_bug.cgi?id=6857 --- Comment #14 from deadalnix <deadalnix@gmail.com> 2012-05-03 10:45:19 PDT --- (In reply to comment #13) > I apologize but I still think the confusion goes the other way. A good way to arbiter this is to peruse the literature on the subject, as Walter suggested. If going through a book has too much overhead, online articles and presentations should work, too. I can't afford to do much more explaining than essentially reciting material that's out there. For example I'd recommend this: http://www.cs.ucsb.edu/~bultan/courses/272-F08/lectures/Contract.ppt. Slides 19 and 20 should clarify the matter. I did read your document with attention, and looked for some other resources today. That arguments given in such documents validate both the current state of thing and the proposed new behavior. In fact, I have failed to find any documentation/article/whatever about the corner case where both behavior differs. In other terms, as it seems that the corner case hasn't been considered, the proposed solution is *A* solution and not *THE* solution. As, according to given arguments I have found in literature, both behavior are good. If I restate arguments they goes like this : - B can be written way after fizzbuzzA, so shouldn't be able to provide an in contract that break it. - Instance of B can be passed to any code that expect instance of A, so B in contracts can only loosen contract provided by A, not restrict them. I think we all agree on such points. I think we can all agree also that both current behavior and proposed behavior satisfy constraints expressed here. The only case where things differs is the one given as example above. Let's remove the ... to make it fully explicit. class A { void foo(int x) in { assert(x > 0); } body {} } class B : A { void foo(int x) in { assert(x > -2); } body {} } and the function void fizzbuzz(A a) { a.foo(-1); } If I do fizzbuzz(new B()); The current behavior will not raise any error. But, as we see in fizzbuzz's body, it doesn't because the object is of type B, not of type A, because any other instances of subtypes of A or A can cause the fizzbuzz function to fail. We conclude that the fizzbuzz function is only correct if it DOES KNOW that it is manipulating object of type B, because operation done are invalid on object of type A. The erratic behavior of fizzbuzz will not be spotted if I pass an instance of B to fizzbuzz. Still, the code is flawed and waiting to explode any time in the future. The whole point of contract is to spot such a situation. For valid code, both behavior allow the same thing exactly. The proposed behavior allow to spot MORE problems EARLIER, and it is something you want. The only reason fizzbuzz here is correct if because the programmer KNOW only instances of B will be passed to fizzbuzz. I may be wrong, but I'd be happy to discuss that specific case, instead of relying on documentation that do not talk about it. I failed in finding documentation about that specific corner case. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
May 03, 2012 [Issue 6857] Precondition contract checks should be statically bound. | ||||
---|---|---|---|---|
| ||||
Posted in reply to timon.gehr@gmx.ch | http://d.puremagic.com/issues/show_bug.cgi?id=6857 --- Comment #15 from Walter Bright <bugzilla@digitalmars.com> 2012-05-03 11:07:27 PDT --- fizbuzzA(A a) { a.foo(); // A.foo's in contract is valid } If an instance of B is passed to fizbuzzA, then the a.foo() will call B.foo(), and either A.foo's in contract or B.foo's in contract must be valid. There is no error or invalid corner case here. I suspect that you think the contracts are checked based on static typing - they are not, they are done using the virtual type. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
May 03, 2012 [Issue 6857] Precondition contract checks should be statically bound. | ||||
---|---|---|---|---|
| ||||
Posted in reply to timon.gehr@gmx.ch | http://d.puremagic.com/issues/show_bug.cgi?id=6857 --- Comment #16 from Don <clugdbug@yahoo.com.au> 2012-05-03 11:56:47 PDT --- (In reply to comment #15) > fizbuzzA(A a) { > a.foo(); // A.foo's in contract is valid > } > > If an instance of B is passed to fizbuzzA, then the a.foo() will call B.foo(), > and either A.foo's in contract or B.foo's in contract must be valid. > > There is no error or invalid corner case here. > > I suspect that you think the contracts are checked based on static typing - they are not, they are done using the virtual type. This is the issue. WHY are they done based on the virtual type? Checking the contracts based on static typing would detect logical errors in the calling code. Doing it based on the virtual type ignores latent bugs in specific instances where they are harmless. I can't understand why that's a good idea. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
May 03, 2012 [Issue 6857] Precondition contract checks should be statically bound. | ||||
---|---|---|---|---|
| ||||
Posted in reply to timon.gehr@gmx.ch | http://d.puremagic.com/issues/show_bug.cgi?id=6857 --- Comment #17 from deadalnix <deadalnix@gmail.com> 2012-05-03 13:44:36 PDT --- (In reply to comment #15) > fizbuzzA(A a) { > a.foo(); // A.foo's in contract is valid > } > > If an instance of B is passed to fizbuzzA, then the a.foo() will call B.foo(), > and either A.foo's in contract or B.foo's in contract must be valid. > > There is no error or invalid corner case here. > > I suspect that you think the contracts are checked based on static typing - they are not, they are done using the virtual type. We are all well aware that the behavior you describe is the current behavior. However we do think it is not optimal and can be improved because of the corner case mentioned. As you can see in given code, fizbuzzA is an invalid piece of code waiting to explode in your face. And this is what you want to avoid, why we use so much stuff like contracts and unit tests (and, as far as I am concerned in my professional work, code review and static analysis tools). The later the bug is discovered, the more expansive it is to fix, and, if it goes in production, the more damage it can do. We want to avoid as much as we can the risk of having a piece of code waiting to explode deep in the codebase. fizzbuzzA is the typical example of the function that will cost you quite a lot. It is flawed, and waiting to crash the application at any moment. We want to detect that ASAP, and in contract should tell us that ASAP. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
May 03, 2012 [Issue 6857] Precondition contract checks should be statically bound. | ||||
---|---|---|---|---|
| ||||
Posted in reply to timon.gehr@gmx.ch | http://d.puremagic.com/issues/show_bug.cgi?id=6857 --- Comment #18 from Walter Bright <bugzilla@digitalmars.com> 2012-05-03 15:37:00 PDT --- (In reply to comment #17) > As you can see in given code, fizbuzzA is an invalid piece of code waiting to explode in your face. There is no bug in example #14. Please show one where it blows up. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
May 03, 2012 [Issue 6857] Precondition contract checks should be statically bound. | ||||
---|---|---|---|---|
| ||||
Posted in reply to timon.gehr@gmx.ch | http://d.puremagic.com/issues/show_bug.cgi?id=6857 --- Comment #19 from Walter Bright <bugzilla@digitalmars.com> 2012-05-03 15:46:03 PDT --- (In reply to comment #16) > This is the issue. WHY are they done based on the virtual type? > Checking the contracts based on static typing would detect logical errors in > the calling code. Doing it based on the virtual type ignores latent bugs in > specific instances where they are harmless. I can't understand why that's a > good idea. The whole idea of polymorphism is to base things on the virtual type. I don't understand what latent bugs you are referring to. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
May 03, 2012 [Issue 6857] Precondition contract checks should be statically bound. | ||||
---|---|---|---|---|
| ||||
Posted in reply to timon.gehr@gmx.ch | http://d.puremagic.com/issues/show_bug.cgi?id=6857 Stewart Gordon <smjg@iname.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |smjg@iname.com --- Comment #20 from Stewart Gordon <smjg@iname.com> 2012-05-03 16:45:21 PDT --- (In reply to comment #5) > This is incorrect. It must satisfy the precondition for A or any class derived from A. The in contract is part of the API of class A. If you call a method of A with arguments that don't satisfy this contract, you are not conforming to the API. (In reply to comment #10) > It isn't a bug, it is the way it is supposed to work. Nor am I ignoring it - I'm trying to explain it. You're explaining the design you're copying. That's quite different from explaining why you've chosen to copy this particular design to the letter. (In reply to comment #19) > (In reply to comment #16) >> This is the issue. WHY are they done based on the virtual type? Checking the contracts based on static typing would detect logical errors in the calling code. Doing it based on the virtual type ignores latent bugs in specific instances where they are harmless. I can't understand why that's a good idea. > > The whole idea of polymorphism is to base things on the virtual type. What are "things"? If you mean the effect of a call, then yes. This we seem to be all agreed on. If you mean whether a given call is legal, then you could by the same argument insist that called method names must be resolved in the context of the virtual type. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
May 04, 2012 [Issue 6857] Precondition contract checks should be statically bound. | ||||
---|---|---|---|---|
| ||||
Posted in reply to timon.gehr@gmx.ch | http://d.puremagic.com/issues/show_bug.cgi?id=6857 Stewart Gordon <smjg@iname.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |REOPENED Resolution|INVALID | --- Comment #21 from Stewart Gordon <smjg@iname.com> 2012-05-03 17:20:19 PDT --- Let's look at it another way. The relevant basic principle of inheritance is the ability to extend the functionality of a class, i.e. add to what can be done with its objects. There are two main ways in which a class B can extend the functionality of a class A: (a) adding new methods (b) widening the range of legal inputs to an existing method In order for a class user to take advantage of (a), it must have a reference of type B. You can't call these new methods through a reference of type A. To be sound, (b) should be equally subject to this requirement. It might be Walter's decision that, in D, (b) is going to continue to be exempt from this requirement. But then it's a WONTFIX. But otherwise, it's reasonable that some people may want (b) to be subject to the requirement, while others may want it to be exempt from it. It's an open matter of debate, therefore whatever this issue is, it certainly isn't INVALID. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
Copyright © 1999-2021 by the D Language Foundation