Attribute transference from callbacks?

Timon Gehr timon.gehr at gmx.ch
Tue Dec 10 22:21:42 UTC 2024


On 12/9/24 07:47, Manu wrote:
> On Mon, 9 Dec 2024 at 01:51, Timon Gehr via Digitalmars-d <digitalmars- 
> d at puremagic.com <mailto:digitalmars-d at puremagic.com>> wrote:
> 
>     On 12/8/24 06:54, Manu wrote:
>      > Here's the stupidest idea ever: expand inout to take an argument...
>      >
>      > void parseThings(string s, void delegate(Thing) inout(nothrow)
>      > inout(@nogc) sink) inout(nothrow) inout(@nogc)
>      > {
>      >    //...
>      >    sink(Thing());
>      >    //...
>      > }
>      > ...
> 
>     Issue with this is you will still not know which `inout`s match up.
>     This
>     is already an issue with the existing `inout`, which just arbitrarily
>     selects a convention. In particular, it does not really work with
>     higher-order functions the way you'd need it to here.
> 
> 
> Yes, this is obviously an issue, and we have it in D comprehensively; 
> it's the main issue with our 'safe' stuff too; where rust has explicit 
> lifetime attribution... it's essentially the same problem all round; it 
> needs tags that specify things which are associated.
> In lieu of that though, I would say, if there are multiple things marked 
> inout(...) in the way I proposed, you would assume the most pessimistic 
> from the set of possibilities is supplied.
> 
> void inheritAttribs(string s, void delegate() inout(nothrow) 
> inout(@nogc) fun_1, void delegate() inout(nothrow) inout(@nogc) fun_2) 
> inout(nothrow) inout(@nogc)
> {
>    //...
>    fun_1();
>    fun_2();
>    //...
> }
> 
> In this case, `inheritAttribs` would only be nothrow in the event BOTH 
> fun_1 and fun_2 are nothrow, likewise for nogc...
> ...

Well, this is one limitation, but the `inout` on the delegate does not 
even match up with the `inout` on `inheritAttribs` those are already 
different.

This does not compile;

```d
inout(int)* foo(inout(int)* delegate()inout dg,inout(int)* x){
     return x;
}

void main(){
     const(int)* delegate()const dg;
     const(int)* x;
     foo(dg,x); // error
}
```

It seems at least this would need to work.

`inout` is very confusing because different `inout` annotations can get 
conflated or not conflated. It's also the main reason why the 
implementation is unsound, it's not done consistently during type checking.

> 
>      > Surely people have had better ideas? But you get the point, and
>     this is
>      > basically essential to make the 'sink' pattern work at all in D.
>      >
>      > No, no templates; it's not right to generate multiple copies of
>     identical functions just because something it CALLS would transfer
>     an attribute. The function itself is identical no matter the state
>     of any attribute transference, and so this isn't a template problem;
>     it's a pattern matching problem.
> 
>     Well, it can be seen as a homogeneous vs heterogeneous compilation
>     problem. The attributes can still act a bit like template parameters,
>     but only one instance must be created that works for all of them. It's
>     sometimes called parametric polymorphism.
> 
> 
> Right. Do you have examples of this from other languages and how it's 
> expressed? Lifetime's in Rust are the obvious benchmark, but I don't see 
> any evidence that D has a taste for this sort of thing.
> ...

Well, Java, C#, Scala support homogeneous compilation in their generics.

In Haskell everything is polymorphic by default with implicit universal 
quantification over lower-case type parameters.

> I do think that inout could work for all attributes the same as inout 
> does for const (with the same limitations).

Well, as I showed above, those limitations are kind of fatal for your 
use case.

> You could see `inout` as 
> shorthand for `inout(const)` under my suggestion.
> Obviously it must enforce the most restrictive implementation inside the 
> code; my function `inheritAttribs` above must be nothrow and nogc 
> internally, but externally it would allow a mapping from one of the 
> 'input' attributes to the 'output' attribute in a non-templated way.

`inout` also interacts with `immutable`, not only `const`.



More information about the Digitalmars-d mailing list