www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Alias to template instance wokrs, but non-template does not?

reply Q. Schroll <qs.il.paperinik gmail.com> writes:
I have the rather strange question: Why does this work?

     struct S
     {
         int value0;

         alias opApply = opApplyImpl!(int delegate(ref int)); //1
         int opApplyImpl(DG : int delegate(ref int))(scope DG 
callback) //2
         {
             if (auto result = callback(value0)) return result;
             return 0;
         }
     }

      safe pure nothrow  nogc unittest
     {
         S xs = S(3);
         int sum = 0;
         foreach (x; xs) sum += x;
         assert(sum == 3);
     }

But replacing Lines //1 and //2 with

     int opApply(int delegate(ref int) callback)

(replacing the alias to a template instance by equivalent(?) 
non-template code) does not. As far as I know, template 
instantiation should make them exactly the same thing.

The spec does not say anything to this.

Even after replacing //1 by
     alias opApply = opApplyImpl!(int delegate(ref int)  system); 
//1
i.e. marking the callback  system explicitly,
the  safe unittest will still compile!

Using
     xs.opApply((ref int x) { sum += x; return 0; });
in the unittest directly makes it fail. The compiler claims as 
expected that the template instance is not satisfy the conditions 
for either attribute on the unittest.

But somehow, it does respect attributes. An un- safe unittest 
like this

     static bool b = false;  // some global state to break pure
     static foreach (i; 0 .. 4)
     {
         version(failure)
          safe pure nothrow  nogc unittest
         {
             static immutable exc = new immutable Exception("");
             S xs = S(3);
             int* p = &xs.value; // some pointer to break  safe-ty
             foreach (x; xs)
             {
                 static if (i == 0) { p = new int(x); } // 
allocates
                 static if (i == 1) { ++p; } // un- safe
                 static if (i == 2) { b = true; } // impure
                 static if (i == 3) { throw exc; } // throws 
Exceptions
             }
         }
     }

actually shows that any single attribute can be failed, 
suggesting it is the same for all.

Is there some attribute magic in the compiler's opApply 
rewriting? It should be mentioned.

I've filed a bug report [1] some time ago. I'm posting here, 
because I want to understand what's going on here.

A runnable example is here: https://run.dlang.io/is/KQ0tmL

[1] https://issues.dlang.org/show_bug.cgi?id=19706
May 14 2019
parent Dukc <ajieskola gmail.com> writes:
On Tuesday, 14 May 2019 at 14:36:21 UTC, Q. Schroll wrote:
 [snip]
 I've filed a bug report [1] some time ago. I'm posting here, 
 because I want to understand what's going on here.
I read through this post and while I don't know precisely what the compiler is thinking, it seems for me that your reasoning that this is a bug is correct. I quess that either the compiler instantiates opApplyImpl with something else than alias opApply specifies (it shouldn't) or (more likely) template attribute inference malfunctions.
May 15 2019