On Monday, 16 April 2018 at 05:57:01 UTC, Shachar Shemesh wrote:
Consider the following program:

struct S1 {
    enum member = 3;

struct S2 {
    enum member = 2;

struct S3 {

enum prop(T) = __traits(hasMember, T, "member") && T.member==3;

pragma(msg, prop!S1);
pragma(msg, prop!S2);
pragma(msg, prop!S3);

When compiled, it produces:
test.d(12): Error: no property member for type S3
test.d(16): Error: template instance `test.prop!(S3)` error instantiating
test.d(16):        while evaluating pragma(msg, prop!(S3))

If I change the definition of "prop" to:
template prop(T) {
    static if( __traits(hasMember, T, "member") && T.member==3 )
        enum prop = true;
        enum prop = false;

then everything compiles as expected.

It seems that the && evaluation does not stop when the first false is found.

I think the issue is better illustrated with a function:

bool prop(T)()
    if (__traits(hasMember, T, "member"))
        if (T.member == 3)
            return true;

    return false;

In this function there's no way to tell if the function is going to be executed at compile time or at runtime. Therefore the semantics of the whole function need to be valid. Replacing the `if` with a `static if` would solve the problem, as you mentioned. This works because the semantic analysis of `static if` and CTFE evaluation of a function occurs at different phases in the compiler. This post explains this better and in more detail [1]. The issue is that the compiler will do the semantic analysis of `T.member` before it has run CTFE or constant folding on the expression.

Although, one could argue that in your case it's clear that the expression only will be evaluated at compile time, but that's not how the compiler works currently.

[1] https://wiki.dlang.org/User:Quickfur/Compile-time_vs._compile-time

/Jacob Carlborg

Reply via email to