@trusted considered harmful
David Nadlinger
see at klickverbot.at
Sat Jul 28 13:52:32 PDT 2012
On Saturday, 28 July 2012 at 20:22:27 UTC, Jonathan M Davis wrote:
> @property auto save()
> {
> import std.conv;
> alias typeof((*_range).save) S;
> static assert(isForwardRange!S, S.stringof ~ " is not a
> forward range.");
>
> @trusted {auto mem = new void[S.sizeof];}
>
> static if(isSafelyCallable!((){(*_range).save;}))
> {
> @trusted { emplace!S(mem, cast(S)(*_range).save); }
> }
> else
> {
> emplace!S(mem, cast(S)(*_range).save);
> }
>
> @trusted {return RefRange!S(cast(S*)mem.ptr);}
> }
>
> It's still a bit ugly, but it's far better than what we can
> currently do. As
> it stands, you can't even put the emplace call in a separate
> function and mark
> it @trusted or @system depending on save, because the only way
> to mark the
> rest of the function as @trusted is to mark the whole thing as
> @trusted. You'd
> have to specifically put _everything else_ in its own function
> _and_ emplace in
> its own function (one @trusted, one @system) and have the outer
> function call
> both. It's a mess. Being able to mark statements as @trusted
> rather than just
> entire functons would be _huge_.
For the specific case of calling unsafe functions from otherwise
safe code, which occurs quite frequently due to parts of Phobos
not being properly annotated yet, I've been experimenting with an
alternative solution in my code. It allows you to »apply
trusted« at a function call level, and is easily implemented in
the library with today's D – using it RefRange.save would look
like this using it:
---
@property auto save()
{
import std.conv;
alias typeof((*_range).save) S;
static assert(isForwardRange!S, S.stringof ~ " is not a
forward range.");
auto mem = new void[S.sizeof];
TRUSTED!(emplace!S)(mem, cast(S)(*_range).save);
@trusted return RefRange!S(cast(S*)mem.ptr);
}
---
TRUSTED is just a @trusted template function which accepts a
callable via an alias parameter and invokes it with the given
parameters, adding @trusted to the function type via a cast (an
application of std.traits.SetFunctionAttributes, by the way).
It seems to work fine, but there is an obvious catch: Just like
@trusted, TRUSTED circumvents safety, and all of its uses must be
carefully examined. But in contrast to the former, it is not part
of the language, so anyone working on the code base, especially
reviewers, must be aware of implications. The all-caps name is
meant to help drawing attention to .
Maybe it would be a good idea to also allow
`@trusted(emplace!S)(mem, cast(S)(*_range).save)`, with semantics
similar to TRUSTED? Or even applying @trusted to arbitrary
expressions, similar to `checked` in C#?
David
More information about the Digitalmars-d
mailing list