Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
July 08, 2013 Help me investigate a bug to file it. | ||||
---|---|---|---|---|
| ||||
Yeah, not very exiting, but I just spent an hour tracking down the fix, but now I'd like to track down *what* was making it break (my fix was "luck"). This should help Kenji (or others) have an easier time fixing it :) Also, I'm only repro'ing this on linux... I think there are two things involved here. The first, is accessing members of a struct for a static if, in a global scope: //---- import std.stdio; import std.range; struct S(R) { R _input; void foo() { static assert(is(typeof(_input[size_t.max .. size_t.max]))); //ok static assert(is(typeof(_input[size_t.max .. $]))); //ok } static assert(is(typeof(_input[size_t.max .. size_t.max]))); //ok static assert(is(typeof(_input[size_t.max .. $]))); //NOPE! } void main() { auto k = iota(0, 1).cycle(); S!(typeof(k)) s; } //---- As you can see, the static if behaves differently in a function, or in the raw body of the struct. Is this normal? Anybody know what is going on exactly? I'm trying to get more context here... ----------------------------------------------- Second, one of the things I found strange was that only *1* of the two assertions failed. basically, _input[0 .. 1] is fair game, yet, _input[0 .. $] is not? What gives? I put my nose in cycles's opDollar. It is written like this: //---- private static struct DollarToken {} DollarToken opDollar() { return DollarToken.init; } //---- Nothing special about it. Just a function that returns an object. Declaring it const/nothrow/@safe *and* pure does not fix the problem... *HOWEVER* declaring it as a manifest constant *does* fix the issue: //---- private static struct DollarToken {} enum opDollar = DollarToken.init; //---- ------------------------------------------------ I think I've run into "global static ifs using members" issues before, but just figured I wasn't allowed to use them. Apparently, to issue is more subtle than this. I have *no* idea how to file this, I have no idea what the rules are. Any insight? |
July 08, 2013 Re: Help me investigate a bug to file it. | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On 07/08/13 19:54, monarch_dodra wrote: > struct S(R) > { > R _input; > void foo() > { > static assert(is(typeof(_input[size_t.max .. size_t.max]))); //ok > static assert(is(typeof(_input[size_t.max .. $]))); //ok > } > static assert(is(typeof(_input[size_t.max .. size_t.max]))); //ok > static assert(is(typeof(_input[size_t.max .. $]))); //NOPE! > } > As you can see, the static if behaves differently in a function, or in the raw body of the struct. Is this normal? Anybody know what is going on exactly? I'm trying to get more context here... > > ----------------------------------------------- > > Second, one of the things I found strange was that only *1* of the two assertions failed. basically, _input[0 .. 1] is fair game, yet, _input[0 .. $] is not? What gives? I put my nose in cycles's opDollar. It is written like this: Did you really mean size_t.*max* above? Anyway, when '$' is rewritten as 'opDollar' and that is defined as a non-static method, it would be surprising if calling the method did work w/o any context pointer... > //---- > private static struct DollarToken {} > DollarToken opDollar() > { > return DollarToken.init; > } > //---- > Nothing special about it. Just a function that returns an object. Declaring it const/nothrow/@safe *and* pure does not fix the problem... > > *HOWEVER* declaring it as a manifest constant *does* fix the issue: > //---- > private static struct DollarToken {} > enum opDollar = DollarToken.init; > //---- Does declaring the opDollar "function" as `static` fix it? artur |
July 08, 2013 Re: Help me investigate a bug to file it. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Artur Skawina | On Monday, 8 July 2013 at 18:55:30 UTC, Artur Skawina wrote: > On 07/08/13 19:54, monarch_dodra wrote: >> struct S(R) >> { >> R _input; >> void foo() >> { >> static assert(is(typeof(_input[size_t.max .. size_t.max]))); //ok >> static assert(is(typeof(_input[size_t.max .. $]))); //ok >> } >> static assert(is(typeof(_input[size_t.max .. size_t.max]))); //ok >> static assert(is(typeof(_input[size_t.max .. $]))); //NOPE! >> } > >> As you can see, the static if behaves differently in a function, or in the raw body of the struct. Is this normal? Anybody know what is going on exactly? I'm trying to get more context here... >> >> ----------------------------------------------- >> >> Second, one of the things I found strange was that only *1* of the two assertions failed. basically, _input[0 .. 1] is fair game, yet, _input[0 .. $] is not? What gives? I put my nose in cycles's opDollar. It is written like this: > > Did you really mean size_t.*max* above? Yeah. It's not a runtime test. In this case, I *also* need to make sure that the slie operation accepts a size_t arg. If I use size_t.min, it statically evaluates to zero, so the test becomes sens-less: saying "fun(size_t.min)" works doesn't actually guarantee you can pass a size_t: it may actually only accepts ubytes or short indexing. But I guess that is a detail in the scope of the original problem. > Anyway, when '$' is rewritten as 'opDollar' and that is defined > as a non-static method, it would be surprising if calling the > method did work w/o any context pointer... But, the "context pointer" *should* be defined as whatever the owner of the indexing/slicing object is, no? In this case, it's simply _input. It has nothing to do with the "this" pointer being available... If anything, it kind of worries me about *what* the implementation is doing with the this pointer, but I haven't been able to "trick" it into calling a wrong function. > Does declaring the opDollar "function" as `static` fix it? > > artur Yes. It does fix it. I think you put your finger exactly on where the issue is. I'll report it in the morning. Thank you for participating :) |
July 08, 2013 Re: Help me investigate a bug to file it. | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On 07/08/13 23:45, monarch_dodra wrote: > On Monday, 8 July 2013 at 18:55:30 UTC, Artur Skawina wrote: >> On 07/08/13 19:54, monarch_dodra wrote: >>> struct S(R) >>> { >>> R _input; >>> void foo() >>> { >>> static assert(is(typeof(_input[size_t.max .. size_t.max]))); //ok >>> static assert(is(typeof(_input[size_t.max .. $]))); //ok >>> } >>> static assert(is(typeof(_input[size_t.max .. size_t.max]))); //ok >>> static assert(is(typeof(_input[size_t.max .. $]))); //NOPE! >>> } >> >>> As you can see, the static if behaves differently in a function, or in the raw body of the struct. Is this normal? Anybody know what is going on exactly? I'm trying to get more context here... >>> >>> ----------------------------------------------- >>> >>> Second, one of the things I found strange was that only *1* of the two assertions failed. basically, _input[0 .. 1] is fair game, yet, _input[0 .. $] is not? What gives? I put my nose in cycles's opDollar. It is written like this: >> >> Did you really mean size_t.*max* above? > > Yeah. It's not a runtime test. In this case, I *also* need to make sure that the slie operation accepts a size_t arg. If I use size_t.min, it statically evaluates to zero, so the test becomes sens-less: saying "fun(size_t.min)" works doesn't actually guarantee you can pass a size_t: it may actually only accepts ubytes or short indexing. Didn't think of that; these implicit narrowing conversion can be, umm, surprising. But as long as the right overload gets picked, I guess they're safe. Thanks for the explanation. >> Anyway, when '$' is rewritten as 'opDollar' and that is defined as a non-static method, it would be surprising if calling the method did work w/o any context pointer... > > But, the "context pointer" *should* be defined as whatever the owner of the indexing/slicing object is, no? In this case, it's simply _input. It has nothing to do with the "this" pointer being available... > > If anything, it kind of worries me about *what* the implementation is doing with the this pointer, but I haven't been able to "trick" it into calling a wrong function. It's just like struct S { auto opDollar() { return 42; } enum a = opDollar(); } This can't work - there is no S object to call the method with. enum a = S.init.opDollar(); would work, just as making the method static. >> Does declaring the opDollar "function" as `static` fix it? > > Yes. It does fix it. I think you put your finger exactly on where the issue is. I'll report it in the morning. Thank you for participating :) Thank you for still trying to improve the std lib. I gave up on using it, other than for toy examples, long time ago. Hopefully it will be usable at some point. artur |
July 09, 2013 Re: Help me investigate a bug to file it. | ||||
---|---|---|---|---|
| ||||
On 07/09/13 00:43, Artur Skawina wrote:
> On 07/08/13 23:45, monarch_dodra wrote:
>> But, the "context pointer" *should* be defined as whatever the owner of the indexing/slicing object is, no? In this case, it's simply _input. It has nothing to do with the "this" pointer being available...
>>
>> If anything, it kind of worries me about *what* the implementation is doing with the this pointer, but I haven't been able to "trick" it into calling a wrong function.
>
> It's just like
Sorry, didn't read that code again before replying. What is
indeed unintuitive is that the first typeof expression succeeds
but the other one fails. But this is related to how typeof() works,
apparently by design. Eg:
auto f(int a) { return a; }
pragma(msg, typeof(f(1))); // "int". OK.
alias INT = int;
pragma(msg, typeof(f(INT))); // "int". OK...
//pragma(msg, typeof(f(int))); // Compile error.
That plus a non-existing this._input, results in a bit (too much)
magic, and the first test passes. The other one fails because of
the '$' (ie opDollar() call).
artur
|
July 10, 2013 Re: Help me investigate a bug to file it. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Artur Skawina | On Tuesday, 9 July 2013 at 00:06:11 UTC, Artur Skawina wrote: > That plus a non-existing this._input, results in a bit (too much) > magic, and the first test passes. The other one fails because of > the '$' (ie opDollar() call). > > artur In any case, it is now filed: http://d.puremagic.com/issues/show_bug.cgi?id=10597 I reduced it to this (imo) neat usecase: //---- struct R { void opIndex(int); int opDollar(); } R r; void foo() { static assert(is(typeof(r[0]))); //ok static assert(is(typeof(r[$]))); //ok } static assert(is(typeof(r[0]))); //ok static assert(is(typeof(r[$]))); //fails (!) //---- Thanks again for the help :) |
July 10, 2013 Re: Help me investigate a bug to file it. | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On 07/10/13 21:36, monarch_dodra wrote: > On Tuesday, 9 July 2013 at 00:06:11 UTC, Artur Skawina wrote: >> That plus a non-existing this._input, results in a bit (too much) >> magic, and the first test passes. The other one fails because of >> the '$' (ie opDollar() call). > In any case, it is now filed: http://d.puremagic.com/issues/show_bug.cgi?id=10597 > > I reduced it to this (imo) neat usecase: > struct R > { > void opIndex(int); > int opDollar(); > } > R r; > static assert(is(typeof(r[0]))); //ok > static assert(is(typeof(r[$]))); //fails (!) Yeah, I can't convince myself that it's ok for the /first/ assert to pass - actually evaluating the "r[0]" expression in that same context will *fail* (because 'r' isn't known at compile time). It always possible to test with 'typeof(r.init[0])'. The fact that static assert(__traits(compiles, r[0])); succeeds, when that expression won't actually compile is also a problem. artur |
Copyright © 1999-2021 by the D Language Foundation