August 17, 2019 [Issue 20135] New: Tuple assignment incorrectly calls destructor on freshly postblitted structs | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=20135 Issue ID: 20135 Summary: Tuple assignment incorrectly calls destructor on freshly postblitted structs Product: D Version: D2 Hardware: x86_64 OS: Linux Status: NEW Severity: normal Priority: P1 Component: dmd Assignee: nobody@puremagic.com Reporter: destructionator@gmail.com Tested on dmd.2.088.0-beta.1, but also present on older versions I tried, so I don't think it is new. Consider the following code: -------------- import std.stdio; struct Test { string s; this(string s) { this.s = s; } this(this) { this.s ~= " postblitted"; } ~this() { this.s = "destroyed"; } } struct Wrapper { Test s; } void bug(Ranges...)(Ranges _ranges) { auto ranges = _ranges; // notice how in the original, we can still see the "1" in there writeln(_ranges[0]); // but in the copy made from the tuple assignment above, the destructor // has apparently been run on the new object, starts with "destroyed" writeln(ranges[0]); assert(ranges[0].s.s[0 .. "destroyed".length] != "destroyed"); // fails // same thing happens to ranges[1] btw } void main() { Wrapper a = Wrapper(Test("1")); Wrapper b = Wrapper(Test("2")); bug(a, b); } ------------------ The `ranges = _ranges` does everything right - copies the bits, calls the postblit.... then immediately calls the destructor on the freshly postblitted object, leaving s == "destroyed". (then the writeln adds a bunch of other postblits to it, but once it is destroyed, the relevant data is lost and we are in bug city.) This is reduced from a case an IRC user brought up trying to lockstep over some phobos Files. -- |
Copyright © 1999-2021 by the D Language Foundation