The interface's 'in' contract passes if it makes a virtual function call

Steven Schveighoffer via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Nov 4 12:26:58 PST 2014


On 11/4/14 3:01 PM, Ali Çehreli wrote:
> Perhaps I am expecting too much from the current 'in' contract design
> and implementation. ;)
>
> Still, the virtual function call in the following interface's 'in'
> contract should be dispatched to the implementaion in the derived class,
> right?
>
> It seems like mere presence of that virtual function call causes the
> 'in' contract of the interface succeed and the derived's 'in' contract
> never gets called.
>
> import std.stdio;
>
> void main()
> {
>      /* EXPECTATION: The following call should execute both the
>       * base's and the derived's in contracts 50% of the time
>       * because the base's contract fails randomly. */
>      (new C()).foo();
> }
>
> interface I
> {
>      void foo()
>      in {
>          writeln("I.foo.in");
>
>          /* This check succeeds without calling virtualCheck! */
>          assert(virtualCheck());
>      }
>
>      bool virtualCheck();
> }
>
> class C : I
> {
>      void foo()
>      in {
>          writeln("C.foo.in");
>      }
>      body
>      {}
>
>      bool virtualCheck()
>      {
>          writeln("C.virtualCheck");
>
>          /* Fail randomly 50% of the time */
>          import std.random;
>          import std.conv;
>          return uniform(0, 2).to!bool;
>      }
> }
>
> The output has no mention of C.virtualCheck nor C.foo.in:
>
> I.foo.in
>            <-- Where is C.virtualCheck?
>            <-- Where is C.foo.in?
>
> Ali

This looks like a dmd bug. My theory is that the call to virtualCheck is 
going to the WRONG vtbl address. I have seen stuff like this before. It 
likely is calling something like toString. You would have to debug to 
figure it out.

So what I think happens is it calls the wrong virtual function, which 
returns non-zero always, and obviously doesn't print anything, and then 
continues on. I added a writeln("after virtual check") to the in 
contract of I.foo, and it writes that too.

-Steve


More information about the Digitalmars-d-learn mailing list