[Issue 8823] New: static if (A || B) != static if (A) else if (B) in some cases

d-bugmail at puremagic.com d-bugmail at puremagic.com
Sun Oct 14 23:29:23 PDT 2012


http://d.puremagic.com/issues/show_bug.cgi?id=8823

           Summary: static if (A || B) != static if (A) else if (B) in
                    some cases
           Product: D
           Version: D2
          Platform: All
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody at puremagic.com
        ReportedBy: beatgammit at gmail.com


--- Comment #0 from Jameson <beatgammit at gmail.com> 2012-10-14 23:29:18 PDT ---
Test platform:

Fedora 17 Linux 3.5.4-2.fc17.x86_64
DMD64 D Compiler v2.060
rdmd build 20120724


The following works:

import std.stdio;

class A {
    string s;
}

void main() {
    A a = new A;
    foreach (t; __traits(allMembers, A)) {
        static if (
                is(typeof(__traits(getMember, A, t)) == function) || 
                is(typeof(__traits(getMember, a, t)) == function) ||
                t == "Monitor"
        ) {
            continue;
        }

        __traits(getMember, a, t) = "hello";
    }
}

But if I split up the static if, it won't compile:

import std.stdio;

class A {
    string s;
}

void main() {
    A a = new A;
    foreach (t; __traits(allMembers, A)) {
        static if (is(typeof(__traits(getMember, A, t)) == function)) {
            continue;
        } else if (is(typeof(__traits(getMember, a, t)) == function)) {
            continue;
        } else if (t == "Monitor") {
            continue;
        }

        writeln(t);
        __traits(getMember, a, t) = "hello"; // error
    }
}

I get the following errors:

test.d(19): Error: not a property a.toString
test.d(19): Error: not a property a.toHash
test.d(19): Error: not a property a.opCmp
test.d(19): Error: not a property a.opEquals
test.d(19): Error: __traits(getMember,a,"Monitor") is not an lvalue

If I comment out the offending line, I only get "s" as output, as expected.

Also, if I use an else branch instead, I still get a compile error:

import std.stdio;

class A {
    string s;
}

void main() {
    A a = new A;
    foreach (t; __traits(allMembers, A)) {
        static if (is(typeof(__traits(getMember, A, t)) == function)) {
            continue;
        } else if (is(typeof(__traits(getMember, a, t)) == function)) {
            continue;
        } else if (t == "Monitor") {
            continue;
        } else {
            writeln(t);
            __traits(getMember, a, t) = "hello"; // error
        }
    }
}

test.d(18): Error: __traits(getMember,a,"Monitor") is not an lvalue

This is even more curious, because I explicitly accounted for this case (and it
works in the combined static if). As in the above example, commenting out the
offending line works as expected.


What did I expect:

The if/else branches would behave the same at compile time as it's runtime
equivalent. __traits(getMember, a, t) should not be evaluated if any of the
above if/else branches are true, since it would be an unreachable statement
given the continue.

I was very surprised that combining them into one if conditional worked as
expected, but if one works, they all should work.


Notes:

I'm building a marshaller, so only data types should be considered. Since there
is no isVariable for __traits, this must be done in a loop. Many of the members
cannot be marshalled, so this makes for a messy if conditional, so splitting it
up (into checks on static/instance members) can be more readable.

This particular case can be easily avoided, but a more complicated case (one
branch continues and another breaks) would not be so easy to rectify.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------


More information about the Digitalmars-d-bugs mailing list