Nested functions should be exempt from sequential visibility rules

Nick Sabalausky a at a.a
Tue Apr 3 02:24:44 PDT 2012


"Don Clugston" <dac at nospam.com> wrote in message 
news:jlecab$9gh$1 at digitalmars.com...
>
> If you have type inference of function returns, things can get nasty:
>
> void foo()
> {
>      auto b() { return a(); }
>      X x = whatever;
>      auto a() { return x; }
> }
> Now b actually depends on the declaration of x. So it's not enough to say 
> that only function declarations are immune to ordering rules.

Does being inside a function really make the type deduction any harder (or 
different?) than this?:

auto b() { return a(); }
enum X x = whatever;
auto a() { return x; }

> Furthermore, any declaration before x, which calls b(), is using x even 
> though x hasn't been initialized (or even declared) yet. Suddenly all 
> kinds of horrible situations become possible, which could never happen 
> before.
>

(Don't know if this makes any sence, but I'm throwing it out there...)

Suppose we did the approach I mentioned elsewhere in this thread: "the 
compiler rewrites nested func decls as delegate vars and anon funcs". 
Suppose we also use the rule:

"A nested func is not *callable* (by either the parent function *or* another 
nested function) until after (ie "further down in the code") all the sibling 
symbols it accesses have been declared."

If it's reasonable for type deduction to happen before all this (I have no 
idea how realistic that is), then with your example, the compiler first 
deduces the types just like it would outside a function:

void foo()
{
    X b() { return a(); }
    X x = whatever;
    X a() { return x; }
}

Then it gets rewritten:

void foo()
{
    delegate X() b;
    delegate X() a;

    b = X() { return a(); }
    X x = whatever;
    a = X() { return x; }
}

This would now be flagged as an error because "b" is calling "a" before (ie 
"earlier in the code than") all of the symbols "a" accesses (namely "x") 
have been declared. The following would also be an error for the same 
reason:

void foo()
{
    auto b() { return a(); }
    X w = b();
    X x = whatever;
    auto a() { return x; }
}

However, this would still be perfectly ok:

void foo()
{
    X x = whatever;
    auto b() { return a(); }
    auto a() { return x; }
}

Because it turns into:

void foo()
{
    delegate X() b;
    delegate X() a;

    X x = whatever;
    b = X() { return a(); }
    a = X() { return x; }
}

And now, at the point in the code where "b" calls "a", everything "a" 
accesses (namely "x") has *already* been declared and inited. And of couse, 
"b" *can* call "a" because "a" is already declared way at the top.




More information about the Digitalmars-d mailing list