Alias to template instance wokrs, but non-template does not?
Q. Schroll
qs.il.paperinik at gmail.com
Tue May 14 14:36:21 UTC 2019
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- at 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- at 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
More information about the Digitalmars-d-learn
mailing list