On Thursday, 5 February 2015 at 16:50:18 UTC, Steven Schveighoffer wrote:
Reading the thread in bug report https://issues.dlang.org/show_bug.cgi?id=14125 gets me thinking, perhaps @trusted is mis-designed.

At the moment, a @trusted function is the same as a @system function, but is allowed to be called from a @safe function. And that's it.

But a @trusted function may only need to be marked @trusted because of a few lines of code. So we now use this mechanism where we mark the @trusted portions with a lambda or static nested function, and call that internally, and mark the entire function @safe.

The benefit of this is, for the 90% of the code that is @safe, the compiler is used as a tool to check the @safe-ty of the function. For the 10% that isn't, we have contained it and marked it, and we can focus on that portion for scrutiny. This becomes EXTREMELY important when it comes to maintenance.

For example, if a @trusted function has some code added to it, the new code needs to be measured to see if it really is safe to call from a @safe function. This may be no easy feat.

At least with the @trusted inner function/lambda, you limit yourself to the code that has been marked as such, and you don't need to worry about the actual @safe code that is added to the function.

Or do you?... the problem with this mentality is interactions with data inside the @safe code after a @trusted function is called can still be subject to memory safety issues. An example (using static functions for clarity):

void foo() @safe
{
static auto tmalloc(size_t x) @trusted {return (cast(int *)malloc(x * sizeof(int)))[0..x];}
   static void tfree(void[] arr) @trusted {free(arr.ptr);}

   auto mem = tmalloc(100);
   tfree(mem);
   mem[0] = 5;
}

Note that the final line in the function, setting mem[0] to 5, is the only unsafe part. it's safe to malloc, it's safe to free as long as you don't ever refer to that memory again.

But the problem with the above is that @trusted is not needed to apply to the mem[0] = 5 call. And imagine that the mem[0] = 5 function may be simply added, by another person who didn't understand the context. Marking the whole function as safe is kind of meaningless here.

Changing gears, one of the issues raised in the aforementioned bug is that a function like this really should be marked trusted in its entirety. But what does this actually mean?

When we mark a function @safe, we can assume that the compiler has checked it for us. When we mark a function @trusted, we can assume the compiler has NOT checked it for us. But how does this help? A @safe function can call a @trusted function. So there is little difference between a @safe and a @trusted function from an API point of view. I would contend that @trusted really should NEVER HAVE BEEN a function attribute. You may as well call them all @safe, there is no difference.

What I think we need to approach this correctly is that instead of marking *functions* with @trusted, we need to mark *data* and *calls* with @trusted. Once data is used inside a @trusted island, it becomes tainted with the @trusted mark. The compiler can no longer guarantee safety for that data.

So how can we implement this without too much pain? I envision that we can mark lines or blocks inside a @safe function as @trusted (a @trusted block inside a @system function would be a no-op, but allowed). I also envision that any variable used inside the function is internally marked as @safe until it's used in a @trusted block, and then is marked as @trusted (again internally, no requirement to mark in syntax). If at any time during compilation a @trusted variable is used in @safe code, it's a compile error.

There may be situations in which you DO need this to work, and in those cases, I would say a cast(@safe) could get rid of that mark. For example, if you want to return the result of a @trusted call in a @safe function.

Such a change would be somewhat disruptive, but much more in line with what @trusted calls really mean.

I've left some of the details fuzzy on purpose, because I'm not a compiler writer :)

Destroy

-Steve

Hey I like the creativity you're showing. Just to give people a concrete idea, you might show some sample code and illustrate how things work. It sure helps when I'm trying to think about things.

Reply via email to