scope escaping

Adam D. Ruppe destructionator at gmail.com
Thu Feb 6 16:17:05 PST 2014


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).


More information about the Digitalmars-d mailing list