Skip to content

Document opApply as an alias to a function template instance #4142

Open
@dlangBugzillaToGithub

Description

@dlangBugzillaToGithub

Bolpat reported this on 2024-06-26T16:29:41Z

Transferred from https://issues.dlang.org/show_bug.cgi?id=24633

CC List

  • Bolpat

Description

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions