Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inout-like mechanism to infer function attributes from callback attributes #19333

Open
dlangBugzillaToGithub opened this issue Oct 31, 2017 · 4 comments

Comments

@dlangBugzillaToGithub
Copy link

Martin Nowak (@MartinNowak) reported this on 2017-10-31T00:18:56Z

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

CC List

  • Bastiaan Veelo
  • Bolpat

Description

Not being able to correctly attribute methods is a common issue when designing interfaces and classes. While it's often still possible to restrict all derived classes to certain attributes, it's a lot harder to restrict all possible callbacks.

  void toString(scope void delegate(in char[]) @wildcard) @(wildcard nogc safe);

It would be a great help if such a method could be defined, to that @nogc, @safe, pure, and nothrow can be made dependent on the passed in callback, making it possible to call the method in @nogc code, while also passing in a GC using callback.
@dlangBugzillaToGithub
Copy link
Author

dfj1esp02 commented on 2017-10-31T16:58:51Z

Apparently even templates don't help here much:
---
import std.typecons:Nullable;
Nullable!V convert(T,V)(Nullable!T v, scope V delegate(T) c)
{
	if(v.isNull)return Nullable!V();
	return Nullable!V(c(v.get()));
}

void f() pure
{
	Nullable!long v;
	Nullable!int v1=v.convert!(long,int)((a){ return cast(int)a; });
}
---
Error: pure function 'f' cannot call impure function 'convert!(long, int).convert'

@dlangBugzillaToGithub
Copy link
Author

Bastiaan commented on 2024-04-05T18:20:20Z

This came up again at the DLF quarterly meeting April 5, 2024, with industry partners, and Walter asked to make sure there is a feature request. As discussed there:

For arguments and return types of various mutability we have the `inout` keyword that saves us from having to define multiple function overloads[1]. A similar solution for other attributes does not exist.

For example, if you have foreach loops over a struct S both in a @nogc context and with an allocating loop body,
```d
void f()
{
    S s;
    foreach (a; s)
        allocating(a);
}
    
void g() @nogc
{
    S s;
    foreach (a; s)
        nonallocating(a);
}

void allocating(int) {}

void nonallocating(int) @nogc {}
```

then S needs both of these opApply overloads:

```d
    int opApply(scope int delegate(int) dg);
    int opApply(scope int delegate(int) @nogc dg) @nogc;
```

Similar for @safe, nothrow, pure and their permutations.

Templating opApply[2] can help in many of these cases, but problems arise when classes and inheritance get involved[3].

There is a DIP for argument dependent attributes[4] but work on it has stalled.

[1] https://dlang.org/spec/const3.html#inout
[2] https://dlang.org/spec/statement.html#template-op-apply
[3] https://youtu.be/9lOtOtiwXY4?si=KME_ZddnrecMdWOJ&t=359
[4] https://github.com/dlang/DIPs/pull/198

@dlangBugzillaToGithub
Copy link
Author

qs.il.paperinik commented on 2024-06-24T11:32:02Z

This can be done using templates:
```d
int f(DG)(scope DG callback)
{
    return callback("Hello, World");
}

void main() @safe
{
    import std.stdio;
    f((string str) { writeln(str); return 0; });
}
```

For opApply, for some reason, this works:
```d
struct S
{
    private int opApplyImpl(DG)(scope DG dg)
    {
        static if (is(DG : int delegate(string)))
        	return dg("Hello, World!");
		else
            return dg(0, "Hello, World!");
    }
    alias opApply = opApplyImpl!(int delegate(string));
    alias opApply = opApplyImpl!(int delegate(size_t, string));
}

void main() @safe
{
    import std.stdio;
    foreach (s; S())
    {
        static assert(is(typeof(s) == string));
        writeln(s);
    }
    foreach (i, s; S())
    {
        static assert(is(typeof(i) == size_t));
        static assert(is(typeof(s) == string));
        writeln(i, " ", s);
    }
}
```

@dlangBugzillaToGithub
Copy link
Author

dlang-bot commented on 2024-06-26T16:49:28Z

@Bolpat created dlang/dlang.org pull request #3859 "Specify `opApply` as an alias to a function template instance" fixing this issue:

- Fix Bugzilla Issues 23666, 17953, 23116, and 24633

https://github.com/dlang/dlang.org/pull/3859

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant