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