@safe leak fix?

Robert Jacques sandford at jhu.edu
Thu Nov 12 16:29:28 PST 2009


On Thu, 12 Nov 2009 08:56:25 -0500, Steven Schveighoffer  
<schveiguy at yahoo.com> wrote:

> On Thu, 12 Nov 2009 08:45:36 -0500, Jason House  
> <jason.james.house at gmail.com> wrote:
>
>> Walter Bright Wrote:
>>
>>> Jason House wrote:
>>> > At a fundamental level, safety isn't about pointers or references to
>>> > stack variables, but rather preventing their escape beyond function
>>> > scope. Scope parameters could be very useful. Scope delegates were
>>> > introduced for a similar reason.
>>>
>>> The problem is, they aren't so easy to prove correct.
>>
>> I understand the general problem with escape analysis, but I've always  
>> thought of scope input as meaning @noescape. That should lead to easy  
>> proofs. If my @noescape input (or slice of an array on the stack) is  
>> passed to a function without @noescape, it's a compile error. That  
>> reduces escape analysis to local verification.
>
> The problem is cases like this:
>
> char[] foo()
> {
>    char buf[100];
>    // fill buf
>    return strstr(buf, "hi").dup;
> }
>
> This function is completely safe, but without full escape analysis the  
> compiler can't tell.  The problem is, you don't know how the outputs of  
> a function are connected to its inputs.  strstr cannot have its  
> parameters marked as scope because it returns them.
>
> Scope parameters draw a rather conservative line in the sand, and while  
> I think it's a good optimization we can get right now, it's not going to  
> help in every case.  I'm perfectly fine with @safe being conservative  
> and @trusted not, at least the power is still there if you need it.
>
> -Steve

Well something like this should work (note that I'm making the conversion  
 from T[N] to T[] explicit)

auto strstr(T,U)(T src, U substring)
     if(isRandomAccessRange!T &&
        isRandomAccessRange!U &&
        is(ElementType!U == ElementType!T)
{ /* Do strstr */ }

char[] foo() {                     // Returns type char[]
    char buf[100];                  // Of type scope char[100]
    // fill buf                     // "hi" is type immutable(char)[]
    return strstr(buf[], "hi").dup; // returns a lent char[], which is  
dup-ed into a char[], which is okay to return
}

char[] foo2() {                    // Returns type char[]
    char buf[100];                  // Of type scope char[100]
    // fill buf                     // "hi" is type immutable(char)[]
    return strstr(buf[], "hi");     // Error, strstr returns a lent char[],  
not char[].
}

lent char[] foo3() {               // Returns type lent char[]
    char buf[100];                  // Of type scope char[100]
    // fill buf                     // "hi" is type immutable(char)[]
    return strstr(buf[], "hi");     // Error, scope char[] cannot be  
implicitly converted to lent char[] inside a lent char[] function:  
possible escape.
}

char[] foo4() {                    // Returns type char[]
    char buf[100];                  // Of type scope char[100]
    return buf;                     // Error, return type is char[] not  
char[100].
}

char[] foo5() {                    // Returns type char[]
    char buf[100];                  // Of type scope char[100]
    return buf[];                   // Error, return type is char[] not  
scope char[].
}

Here's an (outdated and confusing) proposal I put together a while ago  
(It's pre-DIP): http://prowiki.org/wiki4d/wiki.cgi?OwnershipTypesInD In  
it, I used stack and scope instead of scope and lent.



More information about the Digitalmars-d mailing list