digitalmars.D.learn - Help me investigate a bug to file it.
- monarch_dodra (58/58) Jul 08 2013 Yeah, not very exiting, but I just spent an hour tracking down
- Artur Skawina (7/37) Jul 08 2013 Did you really mean size_t.*max* above?
- monarch_dodra (18/50) Jul 08 2013 Yeah. It's not a runtime test. In this case, I *also* need to
- Artur Skawina (16/49) Jul 08 2013 Didn't think of that; these implicit narrowing conversion can be, umm,
- Artur Skawina (15/21) Jul 08 2013 Sorry, didn't read that code again before replying. What is
- monarch_dodra (20/25) Jul 10 2013 In any case, it is now filed:
- Artur Skawina (10/26) Jul 10 2013 Yeah, I can't convince myself that it's ok for the /first/ assert
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?
Jul 08 2013
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
Jul 08 2013
On Monday, 8 July 2013 at 18:55:30 UTC, Artur Skawina wrote:On 07/08/13 19:54, monarch_dodra wrote: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.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...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? arturYes. 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 :)
Jul 08 2013
On 07/08/13 23:45, monarch_dodra wrote:On Monday, 8 July 2013 at 18:55:30 UTC, Artur Skawina wrote: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.On 07/08/13 19:54, monarch_dodra wrote: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.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?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.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.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. arturDoes 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 :)
Jul 08 2013
On 07/09/13 00:43, Artur Skawina wrote:On 07/08/13 23:45, monarch_dodra wrote: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). arturBut, 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
Jul 08 2013
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). arturIn 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 :)
Jul 10 2013
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
Jul 10 2013