June 26
https://issues.dlang.org/show_bug.cgi?id=24633

          Issue ID: 24633
           Summary: Document opApply as an alias to a function template
                    instance
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P1
         Component: dlang.org
          Assignee: nobody@puremagic.com
          Reporter: qs.il.paperinik@gmail.com

When `opApply` is an alias to an explicit function template instance, the explicit instantiation is used for overload resolution against potentially many `opApply` overloads and it is used to infer the types of `foreach` variables, however, the delegate created by the compiler in the `foreach` body lowering is passed to the function template uninstantiated. By this mechanism, when overloading `opApply`s based on the number of intended `foreach` variables, type inference is possible **and** function attributes (e.g. `@safe`) will be inferred.

Example:
```d
struct A
{
    int opApply(scope int delegate(long) body) => body(42);
}
struct B
{
    int opApply(Body)(scope Body body) => body(42);
}
struct C
{
    int opApplyImpl(Body)(scope Body body) => body(42);
    alias opApply = opApplyImpl!(int delegate(long));
}
void main() @nogc nothrow pure @safe
{
    // Error: `@nogc` function cannot call non-@nogc function `A.opApply`
    // Error: `pure` function cannot call impure function `A.opApply`
    // Error: `@safe` function cannot call `@system` function `A.opApply`
    // Error: function `A.opApply` is not `nothrow`
    foreach (x; A()) { }

    // Error: cannot infer type for `foreach` variable `x`
    foreach (x; B()) { }

    // Good:
    foreach (x; C())
    {
        static assert(is(typeof(x) == long));
        assert(x == 42);
    }
}
```

This behavior is great and should be specified as intended.

--