digitalmars.D.learn - Unittest Absurdity
- Ruby The Roobster (24/24) Aug 04 2022 How do I get unittests to actually execute operator overloads?
- Ruby The Roobster (4/6) Aug 04 2022 Also, this isn't mentioned in the spec.
- jfondren (5/13) Aug 04 2022 unittest blocks are just anonymous functions. They're not a
- jfondren (17/17) Aug 04 2022 On Friday, 5 August 2022 at 01:38:48 UTC, jfondren wrote:
- Ruby The Roobster (3/20) Aug 04 2022 I found the issue: opOpAssign isn't getting called at all. I
- Ruby The Roobster (3/26) Aug 04 2022 Even then, I still have a bug, but that is completely unrelated
- Ruby The Roobster (2/30) Aug 04 2022 Nevermind. I have to remove the trailing equals sign.
- jfondren (32/44) Aug 04 2022 ah, so you had `(op == "/=")` instead?
- Paul Backus (5/7) Aug 04 2022 Given that the example works, the problem must be in some other
- Steven Schveighoffer (5/13) Aug 04 2022 Another option: use -vcg-ast, and have the compiler tell you what it's
- jfondren (37/41) Aug 04 2022 The output's not that useful...
- Steven Schveighoffer (5/27) Aug 05 2022 oof, I expected this to include the template parameters! I believe it
- Steven Schveighoffer (22/29) Aug 05 2022 It does not! I'm genuinely shocked.
- frame (29/33) Aug 05 2022 Sorry, I don't get what you takling about?
- Steven Schveighoffer (33/63) Aug 05 2022 That's not what I was talking about here. I'm talking about `-vcg-ast`
- frame (7/9) Aug 05 2022 Thanks for clarification.
How do I get unittests to actually execute operator overloads? E.g.: ```d struct Struct { void opOpAssign(string op)(Struct rhs) //Assume that the operator `/=` is implemented here { //... } } unittest { Struct a = Struct(1); Struct b = Struct(2); a /= b; assert(a == Struct(5, 0, -1)); } ``` The unittest completely ignores the `a /= b`. Unittests also ignore swapping `a` for `a/b` in the `assert` statement, and even if I force the operator overloads to give me the correct answers, the `assert` still fails. Any function other than an operator overload seems to work fine.
Aug 04 2022
On Friday, 5 August 2022 at 01:23:40 UTC, Ruby The Roobster wrote:[SNIP] Any function other than an operator overload seems to work fine.Also, this isn't mentioned in the spec. Additional Information: Fails for both DMD and LDC on Windows x86_64 for dmd v2.100.1
Aug 04 2022
On Friday, 5 August 2022 at 01:25:50 UTC, Ruby The Roobster wrote:On Friday, 5 August 2022 at 01:23:40 UTC, Ruby The Roobster wrote:unittest blocks are just anonymous functions. They're not a special environment and there's nothing you can do here that wouldn't be necessary in any other user of your code. You have some other problem (which could very well be a compiler bug.)[SNIP] Any function other than an operator overload seems to work fine.Also, this isn't mentioned in the spec. Additional Information: Fails for both DMD and LDC on Windows x86_64 for dmd v2.100.1
Aug 04 2022
On Friday, 5 August 2022 at 01:38:48 UTC, jfondren wrote: Here's a complete example that passes tests: ```d struct S { int n; void opOpAssign(string op)(S rhs) if (op == "/") { n++; } } unittest { auto a = S(1), b = S(2); a /= b; b /= a; assert(a.n == 2); assert(b.n == 3); } ```
Aug 04 2022
On Friday, 5 August 2022 at 01:42:23 UTC, jfondren wrote:On Friday, 5 August 2022 at 01:38:48 UTC, jfondren wrote: Here's a complete example that passes tests: ```d struct S { int n; void opOpAssign(string op)(S rhs) if (op == "/") { n++; } } unittest { auto a = S(1), b = S(2); a /= b; b /= a; assert(a.n == 2); assert(b.n == 3); } ```I found the issue: opOpAssign isn't getting called at all. I have no idea why, though.
Aug 04 2022
On Friday, 5 August 2022 at 01:47:07 UTC, Ruby The Roobster wrote:On Friday, 5 August 2022 at 01:42:23 UTC, jfondren wrote:Even then, I still have a bug, but that is completely unrelated to this issue.On Friday, 5 August 2022 at 01:38:48 UTC, jfondren wrote: Here's a complete example that passes tests: ```d struct S { int n; void opOpAssign(string op)(S rhs) if (op == "/") { n++; } } unittest { auto a = S(1), b = S(2); a /= b; b /= a; assert(a.n == 2); assert(b.n == 3); } ```I found the issue: opOpAssign isn't getting called at all. I have no idea why, though.
Aug 04 2022
On Friday, 5 August 2022 at 01:51:21 UTC, Ruby The Roobster wrote:On Friday, 5 August 2022 at 01:47:07 UTC, Ruby The Roobster wrote:Nevermind. I have to remove the trailing equals sign.On Friday, 5 August 2022 at 01:42:23 UTC, jfondren wrote:Even then, I still have a bug, but that is completely unrelated to this issue.On Friday, 5 August 2022 at 01:38:48 UTC, jfondren wrote: Here's a complete example that passes tests: ```d struct S { int n; void opOpAssign(string op)(S rhs) if (op == "/") { n++; } } unittest { auto a = S(1), b = S(2); a /= b; b /= a; assert(a.n == 2); assert(b.n == 3); } ```I found the issue: opOpAssign isn't getting called at all. I have no idea why, though.
Aug 04 2022
On Friday, 5 August 2022 at 01:53:42 UTC, Ruby The Roobster wrote:ah, so you had `(op == "/=")` instead? I think this is a problem actually, maybe arguably not a bug, but not desirable. Consider: ```d struct S { int n; void opOpAssign(string op)(S rhs) if (op == "/=") { n++; } void opOpAssign(string op)(S rhs) if (op == "/") { // do nothing } } unittest { auto a = S(1), b = S(2); a /= b; b /= a; assert(a.n == 2); assert(b.n == 3); } ``` The test fails because the second definition is used (preventing a "none of the overlords are callable" error) and the first definition never matches because it's wrong. I say this arguably isn't a bug because it can still be used: ```d a.opOpAssign!"/="(b); b.opOpAssign!"/="(a); ``` but what's actually wanted is operator overloading and a mistake at the definition is silently allowed.Nevermind. I have to remove the trailing equals sign.On Friday, 5 August 2022 at 01:38:48 UTC, jfondren wrote: Here's a complete example that passes tests: ```d struct S { int n; void opOpAssign(string op)(S rhs) if (op == "/") { n++; } }
Aug 04 2022
On Friday, 5 August 2022 at 01:47:07 UTC, Ruby The Roobster wrote:I found the issue: opOpAssign isn't getting called at all. I have no idea why, though.Given that the example works, the problem must be in some other part of your code that you haven't posted. If you can post a more complete example that reproduces the problem, we can probably help you fix it.
Aug 04 2022
On 8/4/22 9:51 PM, Paul Backus wrote:On Friday, 5 August 2022 at 01:47:07 UTC, Ruby The Roobster wrote:Another option: use -vcg-ast, and have the compiler tell you what it's actually calling. It's not ignoring that line, it's just not doing what you think it's doing. -SteveI found the issue: opOpAssign isn't getting called at all. I have no idea why, though.Given that the example works, the problem must be in some other part of your code that you haven't posted. If you can post a more complete example that reproduces the problem, we can probably help you fix it.
Aug 04 2022
On Friday, 5 August 2022 at 02:20:31 UTC, Steven Schveighoffer wrote:On 8/4/22 9:51 PM, Paul Backus wrote: Another option: use -vcg-ast, and have the compiler tell you what it's actually calling. It's not ignoring that line, it's just not doing what you think it's doing.The output's not that useful... ```d import object; struct S { int n; void opOpAssign(string op)(S rhs) if (op == "/=") { n++; } void opOpAssign(string op)(S rhs) if (op == "/") { } } unittest { S a = S(1); S b = S(2); a.opOpAssign(b); b.opOpAssign(a); assert(a.n == 2); assert(b.n == 3); } ... ``` With this tiny example code it's clear by the end when there's only this one template instantiation: ```d opOpAssign!"/" { pure nothrow nogc safe void opOpAssign(S rhs) { } } ```
Aug 04 2022
On 8/4/22 10:27 PM, jfondren wrote:The output's not that useful... ```d import object; struct S { int n; void opOpAssign(string op)(S rhs) if (op == "/=") { n++; } void opOpAssign(string op)(S rhs) if (op == "/") { } } unittest { S a = S(1); S b = S(2); a.opOpAssign(b); b.opOpAssign(a);oof, I expected this to include the template parameters! I believe it normally does? This is a bug that should be filed. -Steve
Aug 05 2022
On 8/5/22 11:24 AM, Steven Schveighoffer wrote:On 8/4/22 10:27 PM, jfondren wrote:It does not! I'm genuinely shocked. ```d void foo(string s, T)(T t) {} void main() { foo!"hi"(1); } ``` outputs: ```d void foo(string s, T)(T t) { } void main() { foo(1); return 0; } ```a.opOpAssign(b); b.opOpAssign(a);oof, I expected this to include the template parameters! I believe it normally does?This is a bug that should be filed.Make that an enhancement request -Steve
Aug 05 2022
On Friday, 5 August 2022 at 15:24:16 UTC, Steven Schveighoffer wrote:oof, I expected this to include the template parameters! I believe it normally does? This is a bug that should be filed. -SteveSorry, I don't get what you takling about? The docs says: The expression: `a op= b` is rewritten as: `a.opOpAssign!("op")(b)` There must no "=" to be applied. The compiler creates this: ```d opOpAssign!"/" { pure nothrow nogc safe void opOpAssign(S rhs) { } } ``` as only valid call left. Fine for me since the other template is unused. Same for your example: ```d foo!("hi", int) { pure nothrow nogc safe void foo(int t) { } } ```
Aug 05 2022
On 8/5/22 3:53 PM, frame wrote:On Friday, 5 August 2022 at 15:24:16 UTC, Steven Schveighoffer wrote:That's not what I was talking about here. I'm talking about `-vcg-ast` not telling you how it's calling the function.oof, I expected this to include the template parameters! I believe it normally does? This is a bug that should be filed. -SteveSorry, I don't get what you takling about? The docs says: The expression: `a op= b` is rewritten as: `a.opOpAssign!("op")(b)` There must no "=" to be applied.The compiler creates this: ```d opOpAssign!"/" { pure nothrow nogc safe void opOpAssign(S rhs) { } } ``` as only valid call left. Fine for me since the other template is unused.And what if the other template is used? This is the AST from code that instantiates foo twice, and calls it 3 times. Tell me which calls are which? ```d import object; void foo(string s, T)(T t) { } void main() { foo(1); foo(1); foo(1); return 0; } mixin _d_cmain!(); // omitted for brevity foo!("hi", int) { pure nothrow nogc safe void foo(int t) { } } foo!("bar", int) { pure nothrow nogc safe void foo(int t) { } } ``` -Steve
Aug 05 2022
On Friday, 5 August 2022 at 21:24:13 UTC, Steven Schveighoffer wrote:That's not what I was talking about here. I'm talking about `-vcg-ast` not telling you how it's calling the function.Thanks for clarification. I had that in mind but wasn't sure. I first thought it just get optimized away and in case of name/type collision would create another name for the function but after testing with `static if` it really shows that this assumption was wrong :D
Aug 05 2022