On Saturday, 7 February 2015 at 01:41:19 UTC, Andrei Alexandrescu wrote:
Consider the previous code:
[...]
static trustedRead(int fildes, void* buf, size_t nbyte) @trusted
    {
        return core.sys.posix.unistd.read(fildes, buf, nbyte);
    }
static trustedRealloc(void* p, size_t sz, uint ba = 0, const TypeInfo ti = null) @trusted
    {
        return GC.realloc(p, sz, ba, ti);
    }
    static trustedPtrAdd(void[] buf, size_t s) @trusted
    {
        return buf.ptr+s;
    }
static trustedPtrSlicing(void* ptr, size_t lb, size_t ub) @trusted
    {
        return ptr[lb..ub];
    }

First of all, these little @trusted functions are made obsolete by the new system. They should certainly be omitted.

    @system
    {
immutable fd = core.sys.posix.fcntl.open(name.tempCString(),
            core.sys.posix.fcntl.O_RDONLY);
    }

Next, you have to realize that @system blocks are like 'try' blocks: You don't need brackets if there's only one statement in them.

Here's how I would rewrite what you have written using the new method:

version (Posix) void[] read(in char[] name, size_t upTo = size_t.max)
@trusted
{
    import core.memory;
    // A few internal configuration parameters {
    enum size_t
        minInitialAlloc = 1024 * 4,
        maxInitialAlloc = size_t.max / 2,
        sizeIncrement = 1024 * 16,
        maxSlackMemoryAllowed = 1024;
    // }

@system immutable fd = core.sys.posix.fcntl.open(name.tempCString(),
            core.sys.posix.fcntl.O_RDONLY);
    cenforce(fd != -1, name);
    scope(exit) core.sys.posix.unistd.close(fd);

    stat_t statbuf = void;
@system cenforce(trustedFstat(fd, trustedRef(statbuf)) == 0, name);

    immutable initialAlloc = to!size_t(statbuf.st_size
        ? min(statbuf.st_size + 1, maxInitialAlloc)
        : minInitialAlloc);
    void[] result = uninitializedArray!(ubyte[])(initialAlloc);
    scope(failure) delete result;
    size_t size = 0;

    for (;;)
    {
        @system immutable actual = core.sys.posix.unistd.read(fd,
result.ptr + size, min(result.length, upTo) - size);
        cenforce(actual != -1, name);
        if (actual == 0) break;
        size += actual;
        if (size < result.length) continue;
        immutable newAlloc = size + sizeIncrement;
        @system result = GC.realloc(
result.ptr, newAlloc, GC.BlkAttr.NO_SCAN)[0 .. newAlloc];
    }

    @system return result.length - size >= maxSlackMemoryAllowed
? GC.realloc(result.ptr, size, GC.BlkAttr.NO_SCAN)[0..size]
            : result[0 .. size];
}

Note that I just mechanically your @system blocks with the better form. I didn't arrange for them to be elegant. There's nothing wrong with encapsulating a @trusted sequence in a @system block with brackets, to aid future reviewers in identifying subsequent code thought to be affected by the @system statements. Also, few functions will have their @system blocks more or less evenly distributed throughout like the above function does.

The new proposal will never let you add an unsafe operation without your knowing it. It's definitely the way forward.

Reply via email to