On 2011-03-17 20:31:43 -0400, Walter Bright <newshou...@digitalmars.com> said:

On 3/17/2011 5:02 PM, Andrei Alexandrescu wrote:
 > [...]


I don't disagree with anything you wrote. But I am suggesting that one liners should have a high utility to be justifiably included in Phobos.

---------------------------------

You mentioned wondering where we should draw the line in using asserts to check function inputs as opposed to using enforce. I suggest that line should be when a shared library/dll boundary is crossed. Statically linked libs should use assert.

The reason is straightforward - a shared library/dll cannot know in advance what will be connected to it, so it should treat data coming in from an external source as untrusted input. A statically linked library, on the other hand, is inextricably bound to a specific caller and is debugged/tested as a whole.

This raises the spectre about what to do with Phobos if Phobos is built as a dll.

This would be much easier to work with if the decision about checking "in" contracts was taken at the call site. If user code is compiled with contracts, any user code calling Phobos would check the contracts too, dynamic library or not.

One way to make this work is by making the compiler take the contract as a separate function to call. For instance, this function:

        int test(int i)
        in {
                assert(i >= 0);
        }
        body {
                return 100 / i;
        }

would be split in two:

        int testContract(int i)
        {
                assert(i >= 0);
                return test(i); // could hard-code tail call optimization here
        }
        int test(int i) {
                return 100 / i;
        }

If the function that calls this test function is compiled with contracts turned on, it substitutes the call to test() for a call to testContract(), and the contracts gets checked. The testContract() function does not necessarily need to be part of the library, it can be instantiated as needed at the call point.

It could even work with virtual functions: if test() is virtual, testContract() would remain non-virtual and a call to the virtual function test() would be replaced with a call to the non-virtual function testContract() (which would be charged to call test).

There's two concerns however:

1. the contract would be checked against the static type instead of the dynamic type as it is right now. Checking against the dynamic type would require a new slot on the vtable -- or a separate vtable, perhaps inside of the ClassInfo -- which would require contracts for public and protected functions to be part of the library at all times.

2. taking the address of a function (or a delegate) could give you the one that includes the contract if contracts are turned on, but that would mean that code compiled with contracts and code compiled without them would get different addresses for the same function inside of the same executable, which could break some expectations.


--
Michel Fortin
michel.for...@michelf.com
http://michelf.com/

Reply via email to