www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Why is my pure function system when placed in a struct?

reply Q. Schroll <qs.il.paperinik gmail.com> writes:
I have a template function `fImpl` I whish to instantiate 
manually using the new name `f`. Reason is simple: `f` should not 
be a template, but overloading it makes it easier that way.
Nothing's more simple in D:

     int fImpl(T)(T value) { return cast(int) value; }
     alias f = fImpl!int;
     alias f = fImpl!long;

It works perfectly used like that.

In my case, `T` isn't just a simple type, it's a delegate type. 
So it's rather like this:

     alias BaseDG = int delegate(ref int);
     int fImpl(DG : BaseDG)(scope DG callback)
     {
         // NB: this is  safe iff callback is  safe
         int x = 0;
         return callback(x);
     }

     alias myDG = int delegate(ref int)  safe;
     alias f = fImpl!myDG;

When I ask the compiler, if `f` is  safe, it tells me: Hurray, it 
is!

     pragma(msg, __traits(getFunctionAttributes, f)); // tells me: 
`f` is  safe

For whatever reason, when I put the code in a struct, the  safe 
testing line tells me, it's  system now.

     struct S
     {
         // static: // static or not does not matter

         alias BaseDG = int delegate(ref int);
         int fImpl(DG : BaseDG)(scope DG callback) { return 0; }

         alias myDG = int delegate(ref int)  system;
         alias f = fImpl!myDG;

         pragma(msg, __traits(getFunctionAttributes, f)); // tells 
me: `f` is  system
     }

I have no idea why. It is irrelevant if the function template is 
`static` or even does not call the callback.
Feb 27 2019
next sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Wednesday, 27 February 2019 at 17:23:21 UTC, Q. Schroll wrote:
 I have a template function `fImpl` I whish to instantiate 
 manually using the new name `f`. Reason is simple: `f` should 
 not be a template, but overloading it makes it easier that way.
 Nothing's more simple in D:

 [...]
the struct gets drawn into your delegate-context. and I guess that taints the function.
Feb 27 2019
parent Dukc <ajieskola gmail.com> writes:
On Wednesday, 27 February 2019 at 18:06:49 UTC, Stefan Koch wrote:
 the struct gets drawn into your delegate-context.
 and I guess that taints  the function.
Even if it did, it should not make the delegate system. And it does not, since this manifest with static functions and function pointers too.
Feb 27 2019
prev sibling parent reply Dukc <ajieskola gmail.com> writes:
On Wednesday, 27 February 2019 at 17:23:21 UTC, Q. Schroll wrote:
 For whatever reason, when I put the code in a struct, the  safe 
 testing line tells me, it's  system now.
I tested a bit, and it appears that attribute inference is not done at all for templates inside structs -the attribute need not be a delegate: struct S { static int fImpl(Ret)() { return Ret.init; } pragma(msg, __traits(getFunctionAttributes, fImpl!int)); // still tells us: `f` is system } void main(){} A bug, unless I'm overlooking something.
Feb 27 2019
parent ag0aep6g <anonymous example.com> writes:
On 27.02.19 19:10, Dukc wrote:
 I tested a bit, and it appears that attribute inference is not done at 
 all for templates inside structs -the attribute need not be a delegate:
 
 struct S
      {
          static int fImpl(Ret)() { return Ret.init; }
 
          pragma(msg, __traits(getFunctionAttributes, fImpl!int)); // 
 still tells us: `f` is  system
      }
 
 void main(){}
 
 A bug, unless I'm overlooking something.
It's not quite as simple as that. When you put the pragma in a function, the inferred attributes show up: ---- struct S { void f()() {} } pragma(msg, __traits(getFunctionAttributes, S.f!())); /* system */ void g() { pragma(msg, __traits(getFunctionAttributes, S.f!())); /* Same line now says safe. */ } ---- But I agree that this can't be right.
Feb 27 2019