Escape Analysis on reddit

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Fri Oct 31 14:22:20 PDT 2008


Steven Schveighoffer wrote:
> "Walter Bright" wrote
>> http://www.reddit.com/r/programming/comments/7akzd/escape_analysis/
> 
> The question is, in the example:
> 
> int* bar(int* p) { return p; }
> int* foo()
> {
>     int x = 3;
>     return bar(&x);
> }
> 
> where is the problem?  Is the problem in bar, or is the problem in foo?
> 
> The real problem is in foo, because there's technically nothing wrong with 
> bar.

The problem is that foo does not know enough about bar to deem the call 
correct. Notice that if you consider local functions instead of ints, 
that gets you straight to the delegates case that is the crux of the matter.

> So what ends up happening in your scheme is this:
> 
> int *bar(int *p) { return p;}
> 
> void foo(scope int *p)
> {
>    int *x = bar(p); // no escape, but compile error
> }

Well I was talking to Walter how in compiling a function there are two 
scopes to track: that of parameters, and that of locals inside 
functions. The former includes the latter. Bar should be defined as:

scope int* bar(scope int* p) { return p; }

which is easy to check as long as some conservativeness is acceptable.

> So yes, you are protected, but at the cost of not being able to write code 
> that is provably safe.  The end result is you end up removing scope where it 
> really should be, and then virally, it makes you remove scope decorations 
> everywhere else.  I predict that if this is implemented, nobody will be able 
> to use it.

There are many cases in which statically typed programs disallow valid 
constructs. Each case is a matter of nuance, but by and large types have 
turned out to be successful.

> In order for this to be useful, we need to have a way to express total 
> relationships between parameters and the return value.  And that would 
> probably be so convoluted that it's not worth the syntax.

I don't think there is a need to express the exact relationship.

> I'll reiterate my challenge from another thread:
> 
> void f(ref int *a, int *b, int *c) { if(*b < *c) a = b;  else a = c;}
> 
> struct S
> {
>    int *v;
> }
> 
> int *f2(S* s) { return s.v;}
> 
> void f3(ref int *a, ref int *b, ref int *c)
> {
>    int *tmp = a;
>    a = b; b = c; c = tmp;
> }
> 
> void f4()
> {
>    int a=1, b=2, c=3;
>    auto ap = &a;
>    auto bp = &b;
>    auto cp = &c;
>    S s(cp);
> 
>    f(ap, bp, cp);
>    b = *f2(&s);
>    f3(ap, bp, cp);
> }
> 
> Please tell me how I should mark f, S, f2, and f3 such that f4 compiles. 
> Note that this code all works in D1 and provably has no problems with 
> escaping values, since f4 returns void, and no globals are accessed.

First off, we need to clarify that "provably" is a bit strong, and that 
the hypothesis "f4 returns void, and no globals are accessed" is not all 
that's needed for the proof. Full access to function bodies is 
necessary. Correctness may be provable to a human or machine having 
access to the entire body of code, but not if e.g. f, f2, and f3 are 
invisible to f4.

Second, I contest the entire example. Static typing is supposed to prove 
interesting properties about *most* correct programs, at the cost of 
disallowing a *few* correct programs that are not very frequent, are not 
very interesting, or can be easily replaced with typesafe alternatives. 
One can write correct code based on void* that is virtually impossible 
to typecheck statically, but that doesn't show that static types are 
useless.


Andrei



More information about the Digitalmars-d mailing list