Fifth Draft: Primary Type Syntax
Quirin Schroll
qs.il.paperinik at gmail.com
Mon Dec 23 02:47:32 UTC 2024
The obligatory
[permalink](https://github.com/Bolpat/DIPs/blob/e9ab3c3c92e23931c8fcb47f8e55f60864d9196f/DIPs/DIP-2NNN-QFS.md#maximal-munch-exceptions) and [latest draft](https://github.com/Bolpat/DIPs/blob/PrimaryTypeSyntax/DIPs/DIP-2NNN-QFS.md).
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](https://github.com/Bolpat/DIPs/blob/PrimaryTypeSyntax/DIPs/DIP-2NNN-QFS.md#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
```d
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](https://github.com/dlang/dmd/pull/20589) 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:
```d
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:
```d
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)`:
```d
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.
More information about the dip.development
mailing list