On Thursday, 6 February 2014 at 23:27:06 UTC, Meta wrote:
I know very little about compilers, but wouldn't figuring out if a variable is being escaped to an outer scope require flow anyalysis?

I might be using the word wrong too, but I don't think so. All the information needed is available right at the assignment point:

int[] a;
void foo() {
   scope int[] b;
   a = b; // this line is interesting
}

At that line alone, everything we need to know is available. The compiler currently has this code:

    if (e1->op == TOKvar &&
        (((VarExp *)e1)->var->storage_class & STCscope) &&
        op == TOKassign)
    {
        error("cannot rebind scope variables");
    }


If a was marked scope, it would trigger that. But I don't think this is a particularly useful check, at least not alone. We could try this though:

    if (
        e1->op == TOKvar &&
        !(((VarExp *)e1)->var->storage_class & STCscope) &&
        e2->op == TOKvar &&
        (((VarExp *)e2)->var->storage_class & STCscope) &&
        op == TOKassign)
    {
        error("cannot assign scope variables to non-scope");
    }


Now, that line will fail with this error - scope to non-scope is not allowed.

If we add scope to the a variable, the existing compiler code will trigger an error

test500.d(41): Error: cannot rebind scope variables

But I don't like that - it is /too/ conservative (although these two checks together more or less achieve the first step I want). However, what if we take that check out, can we allow rebinding but only to the same or lower scopes?

Well, the VarExp->var we have on the left-hand side has info about the variable's parent.... and we can check that. I'd like to point out that this is WRONG but I don't know dmd that well either:

    if (
        e1->op == TOKvar &&
        (((VarExp *)e1)->var->storage_class & STCscope) &&
        e2->op == TOKvar &&
        (((VarExp *)e2)->var->storage_class & STCscope) &&
        op == TOKassign)
    {
        Declaration* v1 = ((VarExp*)e1)->var;
        Declaration* v2 = ((VarExp*)e2)->var;
        if(v1->parent != v2->parent)
           error("cannot assign scope variable to higher scope");
    }


But this prohibits it from passing outside the function. A more correct check would be to ensure v1 is equal to or a parent of v2... and using whatever is needed to handle inner scopes inside a function.


tbh I don't know just what to look at to get the rest of the scope, but since the compiler can identify what this name actually refers to somehow, it must know where the declaration comes from too! I just don't know where exactly to look.



Of course, the tricky part will be structs, but the same basic idea of the implementation should work (if we can get it working first for basic assignments).

Reply via email to