14 hours ago

The obligatory permalink and latest draft.

Sorry for the inactivity, I had very little spare time in the last months and D is not my top priority.


The new section is § Scope guards. In the monthly meeting I participated in, Walter made me aware that scope guards were designed to be extensible in the future, i.e. between the parentheses, arbitrary tokens should be allowed and nothing else should infringe on this design.

The newly proposed changes incorporate this design decision, requiring scope guards with hypothetical multi-token arguments (think scope(failure, FormatException e) for example) to have braced statements. This is so that

scope (ref int delegate()) dg = &obj.f;

works as expected and isn’t parsed as a scope guard. I’m somewhat adamant to the idea that this just works.

I updated the implementation so it incorporates the compromise and is up-to-date with DMD’s master.


I was asked to include a section about other ambiguities, in particular, align and extern. Notably, those are fine using Maximum Munch. No “Bad Things” happen, only Annoying Things.

For example, in an align(n) context, one can add default-aligned declarations using no-argument align, but with primary types, one possibly wants to write align (ref int function()) fp;, but align greedily takes the type as its argument. The easiest solution is to add align(default) as an elaborate synonym for no-argument align. This addition has merit irrespective of the DIP and the PR for it is already up.

Likewise, extern takes anything in parentheses after it as its argument. Here, a similar fix is possible: Any extern declaration has a linkage, and repeating the default or currently applying linkage fixes the problem:

extern (ref int function()) fp; // error
// `ref int function()` considered a linkage

extern extern(D) (ref int function()) fp; // good

Also, those issues are only relevant in statement scope, where both align and extern are rare. In declaration scope, one can just use braces:

align { (ref int function()) fp1; } // good
extern { (ref int function()) fp2; } // good

I’m unsure if this little discussion really needs to be part of the DIP.


About function types (not to be confused with function pointer types), I haven’t thought much about them, but several people have asked me about them. Practically speaking, there’s much less need to express them. If you need to pass a function type to a template as an argument, assuming FP expresses the corresponding function pointer type (which the DIP enables for all function pointer types), one can use typeof(*FP.init):

void main()
{
    // works currently:
    static assert(typeof(*void function(int) @safe.init).stringof == "@safe void(int)");

    // the DIP enables also:
    static assert(typeof(*ref int function() @safe.init).stringof == "ref @safe int()");
}

I have no idea why function types even exist. They’re an annoying corner case. Even the spec explicitly says that they’re outside the official grammar.