[Issue 11835] Assert not thrown from contract

d-bugmail at puremagic.com d-bugmail at puremagic.com
Mon Dec 30 15:04:07 PST 2013


https://d.puremagic.com/issues/show_bug.cgi?id=11835


Stewart Gordon <smjg at iname.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |smjg at iname.com
         Resolution|DUPLICATE                   |INVALID


--- Comment #2 from Stewart Gordon <smjg at iname.com> 2013-12-30 15:03:58 PST ---
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."

(In reply to comment #0)
> 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 at 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 - empty

> 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().

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: -------


More information about the Digitalmars-d-bugs mailing list