On 05.08.2018 16:07, Steven Schveighoffer wrote:
I have found something that looks like a bug to me, but also looks like it could simply be a limitation of the foreach construct.

Consider this code:

struct Foo {}

enum isFoo(alias x) = is(typeof(x) == Foo);

void main()
{
     Foo foo;
     assert(isFoo!foo);
     static struct X { int i; Foo foo; }
     X x;
     foreach(i, ref item; x.tupleof)
         static if(is(typeof(item) == Foo))  // line A
             static assert(isFoo!item);      // line B
         else
             static assert(!isFoo!item);
}

Consider just the two lines A and B. If you saw those lines anywhere, given the isFoo definition, you would expect the assert to pass. But in this case, it fails.

What is happening is that the first time through the loop, we are considering x.i. This is an int, and not a Foo, so it assigns false to the template isFoo!item.

The second time through the loop on x.foo, the compiler decides that it ALREADY FIGURED OUT isFoo!item, and so it just substitutes false, even though the item in question is a different item.

So is this a bug? Is it expected?

It's a bug. The two copies of 'item' are not supposed to be the same symbol. (Different types -> different symbols.)

Is it too difficult to fix?
...

Unlikely.

The workaround of course is to use x.tupleof[i] when instantiating isFoo. But it's a bit ugly. I can also see other issues cropping up if you use `item` for other meta things.

-Steve

Reply via email to