Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
March 24, 2021 [Issue 21762] object.destroy may silently fail depending on whether a member function is a template | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=21762 moonlightsentinel@disroot.org changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |moonlightsentinel@disroot.o | |rg Hardware|x86_64 |All OS|Linux |All Severity|normal |regression --- Comment #1 from moonlightsentinel@disroot.org --- Reduced example: ---------------------------------------------- import core.stdc.stdio : puts; struct A(T) { T* address; ~this() { destroy(*address); } } void main() { static struct B { A!B next()(); ~this() { puts("B destroyed"); } } static struct C { A!C next(); ~this() { puts("C destroyed"); } } B b; destroy(b); C c; destroy(c); } ---------------------------------------------- Introduced by https://github.com/dlang/druntime/pull/1312. But it's probably a DMD issue because the PR introduced __traits(hasMember, S, "__xdtor") which is true for B but false for C -- |
March 24, 2021 [Issue 21762] object.destroy may silently fail depending on whether a member function is a template | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=21762 --- Comment #2 from moonlightsentinel@disroot.org --- This is probably caused by the forward reference of the destructors. The non-templated next() instantiates A!C before the semantic of C is done and before __xdtor is generated. A!C's destructor then instantiates destroy which omits the dtor call because it's not yet available. -- |
March 24, 2021 [Issue 21762] object.destroy may silently fail depending on whether a member function is a template | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=21762 --- Comment #3 from moonlightsentinel@disroot.org --- Test case without dependencies: struct A(T) { ~this() { static assert(__traits(hasMember, T, "__xdtor")); } } void main() { static struct B { A!B next(); ~this() {} } static struct C { A!C next()(); ~this() {} } C().next(); } B fails while C compiles just fine. -- |
March 24, 2021 [Issue 21762] object.destroy may silently fail depending on whether a member function is a template | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=21762 --- Comment #4 from moonlightsentinel@disroot.org --- Interestingly, the test case works if B and C are declared outside of main. -- |
March 24, 2021 [Issue 21762] object.destroy may silently fail depending on whether a member function is a template | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=21762 --- Comment #5 from moonlightsentinel@disroot.org --- (In reply to moonlightsentinel from comment #4) > Interestingly, the test case works if B and C are declared outside of main. Seems like this was enabled by https://github.com/dlang/dmd/pull/5075 -- |
March 24, 2021 [Issue 21762] object.destroy may silently fail depending on whether a member function is a template | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=21762 --- Comment #6 from moonlightsentinel@disroot.org --- (In reply to moonlightsentinel from comment #5) > (In reply to moonlightsentinel from comment #4) > > Interestingly, the test case works if B and C are declared outside of main. > > Seems like this was enabled by https://github.com/dlang/dmd/pull/5075 Wrong link: https://github.com/dlang/dmd/pull/5075/commits/8e4676303a688ce3a034b38508b5e5b8c7bfa7e0 -- |
July 01, 2021 [Issue 21762] object.destroy may silently fail depending on whether a member function is a template | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=21762 --- Comment #7 from thomas.bockman@gmail.com --- I ran into this again in a different context. One workaround for the compiler bug is to change the definition of object.destroy to do the work of __xdtor itself when the type has a destructor, but no __xdtor is found: ////////////////////////////////////////////////////////////////// import core.internal.lifetime : emplaceInitializer; import core.internal.traits : hasElaborateDestructor; void destroy(bool initialize = true, T)(ref T obj) if(is(T == struct)) { static if(initialize) { destroy!false(obj); emplaceInitializer(obj); } else static if(hasElaborateDestructor!T) { static if(__traits(hasMember, T, `__xdtor`) && __traits(isSame, T, __traits(parent, obj.__xdtor))) obj.__xdtor(); else { static if(__traits(hasMember, T, `__dtor`) && __traits(isSame, T, __traits(parent, obj.__dtor))) obj.__dtor(); foreach_reverse(ref objField; obj.tupleof) destroy!false(objField); } } } ////////////////////////////////////////////////////////////////// Should I submit a druntime pull request for this? -- |
Copyright © 1999-2021 by the D Language Foundation