https://issues.dlang.org/show_bug.cgi?id=14125

--- Comment #66 from Dicebot <pub...@dicebot.lv> ---
Thanks, Walter! This comment alone was more useful and meaningful than rest of
this thread combined :)

Let me use example from the very same std.file to oppose:

S readText(S = string)(in char[] name) @safe if (isSomeString!S)
{
    import std.utf : validate;
    static auto trustedCast(void[] buf) @trusted { return cast(S)buf; }
    auto result = trustedCast(read(name));
    validate(result);
    return result;
}

There are two important bits here:

1) This is verified to be safe only if call to `validate` is safe. Making it
all @trusted would allow to change `validate` to @system and silently break the
promise.

2) Cast is restricted to string types. Pretty much only way it can go wrong is
if function signature changes to allow other types - it is effectively @safe
function that compiler fails to identify as one.

Wrapper is marked @trusted incorrectly but that is intentional. @trusted here
is not used to tell function can actually be trusted but to keep everything
else plain @safe.

Alternative solution is to invert it:

S readText(S = string)(in char[] name) @trusted if (isSomeString!S)
{
    () @safe {
        import std.utf : validate;
        auto s = read(name);
    } ();

    auto result = cast(S) s;

    () @safe {
        validate(result);
    } ();

    return result;
}

Which also solves same problem but it result in creation of much more wrappers
and makes reading the source even harder (even despite the fact I cheated here
and used lambdas instead of nested functions).

--

Reply via email to