digitalmars.D.learn - bug : consecutive function calls and -inline
- noob-is-noob (28/28) May 23 2008 sorry if it has been discussed.
- janderson (31/62) May 24 2008 It seems slightly odd that your implicitly copying T[]. I wonder if
- noob-is-noob (30/43) May 24 2008 Thank you.
- Sivo Schilling (40/88) May 24 2008 I'm not sure that this will suitable to you but if you replace
- janderson (21/68) May 24 2008 Your right about that. Length in an array is simply like a int. That
- Frits van Bommel (9/40) May 24 2008 This definitely looks like a bug to me. However, the second behavior
- noob-is-noob (3/15) May 24 2008 Thank you. I take janderson's advice, change to use class,
sorry if it has been discussed. ===code=== module evbug ; import std.stdio ; struct S(T) { T[] arr ; S!(T) opCall(T a) { arr ~= a ; writefln("%s ", arr) ; return *this ; } } void main() { S!(string) t ; t("AAA")("BBB")("CCC") ; t("<-result") ; } ===output=== v2.014 (similar result for v1.030) 1/ compiled with -inline, ok: [AAA] [AAA BBB] [AAA BBB CCC] [AAA BBB CCC <-result] 2/ compiled w/o -inline, ng: [AAA] [AAA BBB] [AAA BBB CCC] [AAA <-result]
May 23 2008
noob-is-noob wrote:It seems slightly odd that your implicitly copying T[]. I wonder if there's even a defined behavior for copying of array indirectly by struct. I'd imagine that what the second version is doing is copying the structure each time while the first is not. So: T[] a; a.length = 10; ... T[] b; b.length = a.length; b.ptr = a.ptr; b.length += 5; T[] c; c.length = b.length; c.ptr = b.ptr; c.length += 5; //a.length is 10 //b.length is 15 //c.length is 20 Now we try to modify the first element again (which is what your doing). a.length += 5; //a.length is now 15 //b.length is still 15 //c.length is still 20 It maybe that the second version is the correct behavior. Maybe the compiler shouldn't let you copy structs implicitly if you have pointers or arrays in them. Tip. Try using pointers or a class. How that helps. -Joelsorry if it has been discussed. ===code=== module evbug ; import std.stdio ; struct S(T) { T[] arr ; S!(T) opCall(T a) { arr ~= a ; writefln("%s ", arr) ; return *this ; } } void main() { S!(string) t ; t("AAA")("BBB")("CCC") ; t("<-result") ; } ===output=== v2.014 (similar result for v1.030) 1/ compiled with -inline, ok: [AAA] [AAA BBB] [AAA BBB CCC] [AAA BBB CCC <-result] 2/ compiled w/o -inline, ng: [AAA] [AAA BBB] [AAA BBB CCC] [AAA <-result]
May 24 2008
janderson wrote:noob-is-noob wrote:Thank you. But it seems not related to array copying. I've tried with a more basic data type. ==code== import std.stdio ; class A { int c = 0 ; A opCall(int b) { c = c + b ; writefln(c) ; return this ; } } struct B { int c = 0 ; B opCall(int b) { c = c + b ; writefln(c) ; return *this ; } } void main() { A a = new A ; B b ; a(1)(2)(3) ; a(0) ; b(1)(2)(3) ; b(0) ; } ==output=== (edited) -inline version: 1 3 6 6 <- class A 1 3 6 6 <- struct B non-inline version: 1 3 6 6 <- class A 1 3 6 1 <- struct B sorry for my bad English.It seems slightly odd that your implicitly copying T[]. I wonder if there's even a defined behavior for copying of array indirectly by struct. I'd imagine that what the second version is doing is copying the structure each time while the first is not. So: < snip old code > How that helps. -Joelsorry if it has been discussed.<snip old code>
May 24 2008
noob-is-noob Wrote:janderson wrote:I'm not sure that this will suitable to you but if you replace the struct in your code with a pointer to a struct it works. Ok it looks ugly but you can use opCall only on structs not pointer to structs. ===code=== module structptr; import std.stdio; struct S { int c; S* opCall(int cc) { c += cc; writef(c, " "); return this; } } void main() { // use an S on the heap auto t = new S; (*(*(*t)(1))(2))(3); (*t)(0); writefln("\n========"); // use an S on the stack S s; S* sp = &s; (*(*(*sp)(1))(2))(3); (*sp)(0); } ===end of code=== output (compiled without -inline !): 1 3 6 6 ======== 1 3 6 6 as expected. With classes you don't go into such problems because they are always references to heap or stack allocated memory. Regards.noob-is-noob wrote:Thank you. But it seems not related to array copying. I've tried with a more basic data type. ==code== import std.stdio ; class A { int c = 0 ; A opCall(int b) { c = c + b ; writefln(c) ; return this ; } } struct B { int c = 0 ; B opCall(int b) { c = c + b ; writefln(c) ; return *this ; } } void main() { A a = new A ; B b ; a(1)(2)(3) ; a(0) ; b(1)(2)(3) ; b(0) ; } ==output=== (edited) -inline version: 1 3 6 6 <- class A 1 3 6 6 <- struct B non-inline version: 1 3 6 6 <- class A 1 3 6 1 <- struct B sorry for my bad English.It seems slightly odd that your implicitly copying T[]. I wonder if there's even a defined behavior for copying of array indirectly by struct. I'd imagine that what the second version is doing is copying the structure each time while the first is not. So: < snip old code > How that helps. -Joelsorry if it has been discussed.<snip old code>
May 24 2008
noob-is-noob wrote:janderson wrote:Your right about that. Length in an array is simply like a int. That is an array is: struct Array(T) { uint Length; T* t; } so if you put that in your struct you get: struct MyStruct { uint Length; //This T* t; } My point is that it is more bug prone when you start having different lengths pointing to the same array. The other thing is that when you exceed a the available memory in the slot the array was allocated, t will change in that one place to a new location. It won't change in any of the other copies. You might also try a pointer to an array. -Joelnoob-is-noob wrote:Thank you. But it seems not related to array copying. I've tried with a more basic data type. ==code== import std.stdio ; class A { int c = 0 ; A opCall(int b) { c = c + b ; writefln(c) ; return this ; } } struct B { int c = 0 ; B opCall(int b) { c = c + b ; writefln(c) ; return *this ; } } void main() { A a = new A ; B b ; a(1)(2)(3) ; a(0) ; b(1)(2)(3) ; b(0) ; } ==output=== (edited) -inline version: 1 3 6 6 <- class A 1 3 6 6 <- struct B non-inline version: 1 3 6 6 <- class A 1 3 6 1 <- struct B sorry for my bad English.It seems slightly odd that your implicitly copying T[]. I wonder if there's even a defined behavior for copying of array indirectly by struct. I'd imagine that what the second version is doing is copying the structure each time while the first is not. So: < snip old code > How that helps. -Joelsorry if it has been discussed.<snip old code>
May 24 2008
noob-is-noob wrote:sorry if it has been discussed. ===code=== module evbug ; import std.stdio ; struct S(T) { T[] arr ; S!(T) opCall(T a) { arr ~= a ; writefln("%s ", arr) ; return *this ; } } void main() { S!(string) t ; t("AAA")("BBB")("CCC") ; t("<-result") ; } ===output=== v2.014 (similar result for v1.030) 1/ compiled with -inline, ok: [AAA] [AAA BBB] [AAA BBB CCC] [AAA BBB CCC <-result] 2/ compiled w/o -inline, ng: [AAA] [AAA BBB] [AAA BBB CCC] [AAA <-result]This definitely looks like a bug to me. However, the second behavior (w/o -inline) is the correct one. opCall returns a *copy* of the struct it's called on, so only the initial call in each sequence should modify the original. The other two should modify copies. That means only "AAA" and "<-result" should be in t.arr at the end of main(). Since GDC gets this right, it's probably a bug in the DMD inliner. I've entered this into bugzilla: <http://d.puremagic.com/issues/show_bug.cgi?id=2127>
May 24 2008
Frits van Bommel wrote:noob-is-noob wrote:Thank you. I take janderson's advice, change to use class, and avoid return struct *this.<snip>This definitely looks like a bug to me. However, the second behavior (w/o -inline) is the correct one. opCall returns a *copy* of the struct it's called on, so only the initial call in each sequence should modify the original. The other two should modify copies. That means only "AAA" and "<-result" should be in t.arr at the end of main(). Since GDC gets this right, it's probably a bug in the DMD inliner. I've entered this into bugzilla: <http://d.puremagic.com/issues/show_bug.cgi?id=2127>
May 24 2008