@safe inference fundamentally broken
Steven Schveighoffer via Digitalmars-d
digitalmars-d at puremagic.com
Thu Jun 5 11:09:44 PDT 2014
I was just viewing an interesting pull request. The pull wanted to change
a line like this (buf is a fixed-size stack allocated array):
auto x = buf.ptr[0..buf.len];
To this:
auto trustedBuffer(ref typeof(buf) b) @trusted { return b.ptr[0..buf.len];
}
for the sake of allowing the enclosing template function to be inferred
@safe. But the interesting thing is that the original line is DELIBERATELY
that way to PREVENT the compiler from inferring @safety (the buffer could
potentially be squirreled away somewhere).
I questioned the idea of using the .ptr trick to fool the compiler, and
asked why doesn't just do the correct thing. Turns out, the compiler is
very bad at determining if stack-allocated data is escaped or returned.
A quick example:
T[] getBuf(T)() @safe
{
T[100] ret;
auto r = ret[];
return r;
}
void main() @safe
{
auto buf = getBuf!int();
}
Note, the above compiles. An interesting thing here is that we have
explicitly marked getBuf as @safe. So what if we want to remove that? It
STILL compiles, because the compiler infers @safety!
In order to fix it, we can either mark the function getBuf as @system, or
do what was done in the original code above. The benefit of using ptr
instead of @system is that it's much less susceptible to someone coming
along and saying "hey look, if I just remove @system, it works!" It also
allows conditionally compiled un- at safe code to be included in the same
function, and let the compiler infer correctly.
But this is extremely alarming. Here we have to be vigilant for anything
like this, and make SURE we explicitly mark this as @system. If there is
some possibility that a function could be inferred @safe or @system
depending on the template parameters, then we would need to write separate
templates for both, or use the .ptr trick above.
This situation is very bad. I personally think that we need to make
slicing a stack-allocated array INVALID in @safe code, and not let that
code be inferred safe. We have already demonstrated an easy way to make an
internal delegate that can be @trusted for one line. That should be used
to work around this limitation.
I propose that we start migrating towards making slicing of stack data
un- at safe, first by making it a warning, enabled with -w. Then making it an
error.
Thoughts?
-Steve
More information about the Digitalmars-d
mailing list