On Friday, 4 January 2013 at 06:30:55 UTC, Sönke Ludwig wrote:
In other words, references returned by a function call that took any references to locals would be tainted as possibly local (in the function local data flow) and thus are not allowed to escape the scope. References derived from non-local refs could still be returned and returning references to
fields from a struct method also works.

---
@safe ref int test(ref int v) {
        return v; // fine
}

@safe ref int test2() {
        int local;
        return test(local); // error: (possibly) returning ref to local
}

@safe ref int test3() {
        int local;
        int* ptr = &test(local); // fine, ptr is tainted 'local'
        return *ptr; // error: (possibly) returning ref to local
}

@safe ref int test4(ref int val) {
return test(val); // fine, can only be a ref to the external 'val' or to a global
}
---

Trying to say that formally:

Definitions:
'Tainter function':
    A function that:
    1. takes at least one of its parameters by reference
    and
    2. returns by reference
        
'Tainting function call':
    A call to a 'tainter function' where at least one of the
    arguments passed by reference is ref to a local variable

Then the rules become:
Function may not return a reference to:
Rule 1: a function-local variable
Rule 2. a value returned by a 'tainting function call'

@safe:

ref int tfun(ref int v) { // tfun tagged 'tainter function'
    ...
}

ref int test1() {
    int local;
    return local; // error by Rule 1
}

ref int test2() {
    int local;
    return tfun(local); // error by Rule 2
}

ref int test3() {
    int local;
    int* ptr = &tfun(local); // ptr tagged 'local'
    return *ptr; // error by Rule 2
}

ref int test4(ref int val) {
    return tfun(val); // fine
}

int global;

ref int test5() {
    int local;
    int* ptr = &tfun(local); // ptr tagged 'local'
    ptr = &global; // ptr's 'local' tag removed
    return *ptr; // fine
}

Reply via email to