Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
August 05, 2018 foreach on a tuple using aliases | ||||
---|---|---|---|---|
| ||||
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? Is it too difficult to fix? 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 |
August 05, 2018 Re: foreach on a tuple using aliases | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Sunday, 5 August 2018 at 14:07:30 UTC, 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? Is it too difficult to fix?
>
> 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
Another workaround would be
´´´
void main()
{
Foo foo;
assert(isFoo!foo);
static struct X { int i; Foo foo; }
X x;
static foreach(i, item; typeof(x).tupleof)
static if(is(typeof(item) == Foo)) // line A
static assert(isFoo!item); // line B
else
static assert(!isFoo!item);
}
´´´
wouldn't it?
|
August 05, 2018 Re: foreach on a tuple using aliases | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | 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 |
August 06, 2018 Re: foreach on a tuple using aliases | ||||
---|---|---|---|---|
| ||||
Posted in reply to Alex | On 8/5/18 10:48 AM, Alex wrote:
> void main()
> {
> Foo foo;
> assert(isFoo!foo);
> static struct X { int i; Foo foo; }
> X x;
> static foreach(i, item; typeof(x).tupleof)
> static if(is(typeof(item) == Foo)) // line A
> static assert(isFoo!item); // line B
> else
> static assert(!isFoo!item);
> }
I did try static foreach, but it doesn't work.
The difference here is you are using typeof(x).tupleof, whereas I want x.tupleof.
Note that in my real code, I do more than just the static assert, I want to use item as a reference to the real field in x.
-Steve
|
August 06, 2018 Re: foreach on a tuple using aliases | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On 8/5/18 11:40 AM, Timon Gehr wrote: > On 05.08.2018 16:07, Steven Schveighoffer wrote: >> 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.) Yep. I even found it has nothing to do with foreach on a tuple: https://run.dlang.io/is/vxQlIi I wonder though, it shouldn't really be a different type that triggers it, right? I mean 2 separate aliases to different variables that are the same type, I would hope would re-instantiate. Otherwise something like .offsetof would be wrong. > >> Is it too difficult to fix? >> ... > > Unlikely. https://issues.dlang.org/show_bug.cgi?id=19145 -Steve |
August 06, 2018 Re: foreach on a tuple using aliases | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 06.08.2018 14:37, Steven Schveighoffer wrote:
> On 8/5/18 11:40 AM, Timon Gehr wrote:
>> On 05.08.2018 16:07, Steven Schveighoffer wrote:
>>> 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.)
>
> Yep. I even found it has nothing to do with foreach on a tuple: https://run.dlang.io/is/vxQlIi
>
> I wonder though, it shouldn't really be a different type that triggers it, right?
It shouldn't.
|
Copyright © 1999-2021 by the D Language Foundation