D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 7459 - Document the workarounds for mutually-called nested functions.
Summary: Document the workarounds for mutually-called nested functions.
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dlang.org (show other issues)
Version: D2
Hardware: All All
: P2 normal
Assignee: Andrej Mitrovic
URL:
Keywords: pull, spec
Depends on:
Blocks:
 
Reported: 2012-02-07 11:04 UTC by timon.gehr
Modified: 2014-04-23 12:18 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description timon.gehr 2012-02-07 11:04:28 UTC
d-programming-language.org/function sez:

Unlike module level declarations, declarations within function scope are processed in order. This means that two nested functions cannot mutually call each other:

void test() {
  void foo() { bar(); } // error, bar not defined
  void bar() { foo(); } // ok
}

The solution is to use a delegate:

void test() {
  void delegate() fp;
  void foo() { fp(); }
  void bar() { foo(); }
  fp = &bar;
}

The proposed solution is unnecessarily complicated and non-optimal. Since nested template functions are instantiated with the state of the symbol table of the lexically first instantiation, this is a superior solution:

void test() {
    void foo()() { bar(); } // ok
    void bar()   { foo(); } // ok
}
Comment 1 hsteoh 2012-12-13 22:29:06 UTC
Ideally, the compiler should allow nested functions to call each other. I understand there are some complications with how declarations inside function scope are processed, but is there a way to treat function declarations differently from variable declarations?
Comment 2 timon.gehr 2012-12-14 00:20:08 UTC
(In reply to comment #1)
> Ideally, the compiler should allow nested functions to call each other.

I agree. Furthermore, ideally the state of the symbol table should the one at the declaration of the template.

> I understand there are some complications with how declarations inside function
> scope are processed, but is there a way to treat function declarations
> differently from variable declarations?

There are no complications specific to local declarations, except maybe some kind of conservative definite initalization analysis. I guess it's just not implemented and the spec has been modelled after the implementation. An implementation would have to make sure to handle mixins correctly. (just looking at syntactic properties is not enough to decide whether something can be forward-referenced because of those.)

string foo(){ return "foo"; }

void fun(){
    string gen(){ return "void "~foo()~"(){ return `baz`; } ";
    mixin(gen());
}

The above code should be a compiler error. (Similar examples can be constructed in unordered scopes.)
Comment 3 timon.gehr 2012-12-14 00:21:05 UTC
(In reply to comment #2)
> ...
> 
> The above code should be a compiler error.

/compiler/compile/s
Comment 4 Andrej Mitrovic 2013-02-06 20:38:11 UTC
Another workaround:

mixin template A()
{
    void foo() { bar(); } // ok
    void bar() { foo(); } // ok
}

void main()
{
    void test() { }
    mixin A!();
}
Comment 5 Andrej Mitrovic 2014-04-23 11:39:50 UTC
The language enhancement to allow this should be filed as a separate bug report. A pull was made to document the current workarounds.

https://github.com/D-Programming-Language/dlang.org/pull/561
Comment 6 github-bugzilla 2014-04-23 12:12:12 UTC
Commits pushed to master at https://github.com/D-Programming-Language/dlang.org

https://github.com/D-Programming-Language/dlang.org/commit/f88fd0903a24e5746fd82ef260f2d49aaf1683d6
Fix Issue 7459 - Document the workarounds for mutually-called nested functions.

https://github.com/D-Programming-Language/dlang.org/commit/aa7d8d6254b2736f21661d6aebbf8b091909e01a
Merge pull request #561 from AndrejMitrovic/Fix7459

Issue 7459 - Document the workarounds for mutually-called nested functions.
Comment 7 Kenji Hara 2014-04-23 12:18:27 UTC
(In reply to timon.gehr from comment #0)
> d-programming-language.org/function sez:
> 
> Unlike module level declarations, declarations within function scope are
> processed in order. This means that two nested functions cannot mutually
> call each other:
> 
[snip]
>
> The proposed solution is unnecessarily complicated and non-optimal. Since
> nested template functions are instantiated with the state of the symbol
> table of the lexically first instantiation, this is a superior solution:
> 
> void test() {
>     void foo()() { bar(); } // ok
>     void bar()   { foo(); } // ok
> }

In issue 12578, I'm proposing a language behavior to accept the code.