www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 23666] New: Recognize template opApply pattern

https://issues.dlang.org/show_bug.cgi?id=23666

          Issue ID: 23666
           Summary: Recognize template opApply pattern
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P1
         Component: dmd
          Assignee: nobody puremagic.com
          Reporter: qs.il.paperinik gmail.com

Normally, when `opApply` is a template, `foreach` variable types cannot be
inferred and must be stated explicitly. I propose an exception to this rule to
make implementing `opApply` with respect to attributes (safe, nogc, pure,
nothrow) easier[1, 2]. 

Basic idea: Make `opApply` a template to infer attributes based on the delegate
argument’s type. If `opApply` is a template with a single template type
parameter that is used as the type of the single function parameter and is
additioanlly constrained to a delegate type, we can use that type to infer
`foreach` variable types.

A minimal example:
```d
struct S
{
    int opApply(DG : int delegate(int))(DG dg)
    {
        return 0;
    }
}
void main()  safe
{
    foreach (x; S()) // infer `int` for x
    { }
}
```

Details:

When all `opApply` function templates in an aggregate have as their first
template parameter a type parameter that is “aptly” constrained[5]
(“aptly”
defined blow), the respective instantiations with the constraint type are valid
(i.e. instantiate `opApply(DG : Constraint)` as `opApply!Constraint`), and the
resulting template instance (a member function) can be called with 1 argument
of the type of the constraint (i.e. `opApply!Constraint(Constraint.init)`
compiles), these member function templates are added to non-template `opApply`
member functions used to determine `foreach` types.

To be “aptly constrained” means that the constraint is a type of the
following
form:
```d
int delegate ParameterList MemberFunctionAttributes`
```
where `ParameterList` and `MemberFunctionAttributes` [3, 4] are defined in the
D grammar.

The parameters of the `ParameterList` in an “apt” constraint are considered
together with `ParameterList`s of non-template `opApply(int delegate
ParameterList MemberFunctionAttributes)` (if any) to find the best match in
terms of number and `ref`-ness. If the best match for a given `foreach`
statement is such a template instance, it is instantiated again with the type
of the `foreach` lambda, where the types of the `foreach` body lambda’s
parameters are set to the types determied by the constraint in the `opApply`
template.

A template `opApply` may have more than one template parameter and more than
one function parameter when the additional parameters have defaults.

[1] Relevant thread:
https://forum.dlang.org/thread/zlzhrzzamwkohturhrhc forum.dlang.org
[2] Relevant post:
https://forum.dlang.org/post/uquebghlhhstkuxtulwf forum.dlang.org
[3] https://dlang.org/spec/function.html#Parameters
[4] https://dlang.org/spec/function.html#MemberFunctionAttributes
[5] https://dlang.org/spec/template.html#Constraint

--
Feb 02 2023