digitalmars.D.bugs - [Issue 11835] New: Assert not thrown from contract
- d-bugmail puremagic.com (98/98) Dec 27 2013 https://d.puremagic.com/issues/show_bug.cgi?id=11835
- d-bugmail puremagic.com (12/12) Dec 29 2013 https://d.puremagic.com/issues/show_bug.cgi?id=11835
- d-bugmail puremagic.com (43/89) Dec 30 2013 https://d.puremagic.com/issues/show_bug.cgi?id=11835
- d-bugmail puremagic.com (7/8) Dec 30 2013 https://d.puremagic.com/issues/show_bug.cgi?id=11835
- d-bugmail puremagic.com (62/62) Dec 30 2013 https://d.puremagic.com/issues/show_bug.cgi?id=11835
- d-bugmail puremagic.com (7/16) Dec 30 2013 https://d.puremagic.com/issues/show_bug.cgi?id=11835
- d-bugmail puremagic.com (15/58) Dec 30 2013 https://d.puremagic.com/issues/show_bug.cgi?id=11835
https://d.puremagic.com/issues/show_bug.cgi?id=11835 Summary: Assert not thrown from contract Product: D Version: D2 Platform: x86_64 OS/Version: Linux Status: NEW Severity: normal Priority: P2 Component: DMD AssignedTo: nobody puremagic.com ReportedBy: chalucha gmail.com PST --- With code like this: import std.stdio; import core.exception; import std.exception; interface IFoo { void test() in { writeln("IFoo.test"); assert(false); } } class Foo : IFoo { abstract void test() in { writeln("Foo.test"); } body{} } class Bar : Foo { override void test() { writeln("Bar.test"); } } unittest { auto bar = new Bar(); assertThrown!AssertError(bar.test()); } I expected, that AssertError should be thrown from interface contract, but only Bar.test is called. With modification: class Bar : Foo { override void test() in { writeln("Bar.test"); } body{} } Foo.test is called this time (Bar.test is not), but AssertError is still not thrown so assertThrown fails. With further modification: class Foo : IFoo { abstract void test() in { writeln("Foo.test"); assert(false); } body{} } Output is: Foo.test IFoo.test Bar.test core.exception.AssertError source/app.d(45): assertThrown failed: No AssertError was thrown. So this time all contracts are called but still no AssertError thrown. With this modification: class Bar : Foo { override void test() in { writeln("Bar.test"); assert(false); } body{} } All contracts are called and AssertError is thrown from Bar.test(). I think that this is a bug related to 6856 but as it seems that even AssertErrors are somehow "eaten" somewhere, I filled this bug so it can be checked too. Tested with DMD 2.064.2 on Gentoo linux -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 27 2013
https://d.puremagic.com/issues/show_bug.cgi?id=11835 timon.gehr gmx.ch changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |RESOLVED CC| |timon.gehr gmx.ch Resolution| |DUPLICATE *** This issue has been marked as a duplicate of issue 6856 *** -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 29 2013
https://d.puremagic.com/issues/show_bug.cgi?id=11835 Stewart Gordon <smjg iname.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |smjg iname.com Resolution|DUPLICATE |INVALID This isn't a duplicate of issue 6856. That issue is about the handling of the situation where an override has no in { ... } block. While the original code sample here is just this, this issue is about variations of this code in which the override _does_ have an in { ... } block. It is a complete misunderstanding of how in contracts work. http://dlang.org/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."With modification: class Bar : Foo { override void test() in { writeln("Bar.test"); } body{} } Foo.test is called this time (Bar.test is not), but AssertError is still not thrown so assertThrown fails.Foo.test has passed, and so there is no need to call Bar.test.With further modification: class Foo : IFoo { abstract void test() in { writeln("Foo.test"); assert(false); } body{} } Output is: Foo.test IFoo.test Bar.test core.exception.AssertError source/app.d(45): assertThrown failed: No AssertError was thrown. So this time all contracts are called but still no AssertError thrown.The AssertError _has_ been thrown - if it hadn't, then Bar.test's in block wouldn't have been called. What the compiler does is to generate code equivalent to: try { try { // Foo.test.in writeln("Foo.test"); assert(false); } catch (AssertError e) { // IFoo.test.in writeln("IFoo.test"); assert(false); } } catch (AssertError e) { // Bar.test.in writeln("Bar.test"); assert(false); } // Bar.test.body - emptyWith this modification: class Bar : Foo { override void test() in { writeln("Bar.test"); assert(false); } body{} } All contracts are called and AssertError is thrown from Bar.test().This is correct. All in contracts have been checked, and they have all failed, therefore an AssertError is thrown back to the original caller. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 30 2013
https://d.puremagic.com/issues/show_bug.cgi?id=11835This isn't a duplicate of issue 6856. ..D'oh. You are right. This is the second time this happens. :o) -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 30 2013
https://d.puremagic.com/issues/show_bug.cgi?id=11835 PST --- Ok, now I see why it is working like that, but consider this sample: interface IFoo { void test() in { writeln("IFoo.test"); assert(false); } } class Foo : IFoo { void test() in { writeln("Foo.test"); } body{} } class Bar : IFoo { void test() in { writeln("Bar.test"); } body{} } as it works now it means, that interface contract will never throw an AssertError, because Foo and Bar tests passes. What is then the point to define contract in the interface if I have to set the same in class definitions of that interface? In upper sample it can be understandable as new "in" contracts are defined, but if I use just this?: interface IFoo { void test() in { writeln("IFoo.test"); assert(false); } } class Foo : IFoo { void test() { writeln("Foo"); } } class Bar : IFoo { void test() { writeln("Bar"); } } here I will definitelly expect that contract defined in interface will be used to check input of actual methods. It just seems weird to me. For example if I write a library with the public interface or abstract class and want to check input params of it so when other project uses it it will check if it is used properly. But as it works now, this is not possible. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 30 2013
https://d.puremagic.com/issues/show_bug.cgi?id=11835... In upper sample it can be understandable as new "in" contracts are defined, but if I use just this?: ... here I will definitelly expect that contract defined in interface will be used to check input of actual methods. ...Me too. This is what issue 6856 covers. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 30 2013
https://d.puremagic.com/issues/show_bug.cgi?id=11835Ok, now I see why it is working like that, but consider this sample: interface IFoo { void test() in { writeln("IFoo.test"); assert(false); } } class Foo : IFoo { void test() in { writeln("Foo.test"); } body{} } class Bar : IFoo { void test() in { writeln("Bar.test"); } body{} } as it works now it means, that interface contract will never throw an AssertError, because Foo and Bar tests passes. What is then the point to define contract in the interface if I have to set the same in class definitions of that interface?To define the legal inputs to IFoo.test, and hence the minimum that implementations of the method must support.here I will definitelly expect that contract defined in interface will be used to check input of actual methods.Foo.test or Bar.test could be called on an object reference of type Foo or Bar. Then it is allowed to use the wider range of inputs that the class-specific version supports. At the moment, the way to just inherit the contract from a superclass or interface is to use in { assert (false); }It just seems weird to me. For example if I write a library with the public interface or abstract class and want to check input params of it so when other project uses it it will check if it is used properly. But as it works now, this is not possible.See issue 6857. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 30 2013