The following code should work but it doesn't with dmd 2.094.2 on Linux systems. https://run.dlang.io/is/kd2GFP ``` import std; void main(string[] args) { alias lessTid = (in Tid a, in Tid b) => a.to!string < b.to!string; auto c = make!(RedBlackTree!(Tid, lessTid)); c.insert(Tid.init); assert(c.length == 1); auto tid1 = spawn(() {}); c.insert(tid1); assert(c.length == 2); auto tid2 = spawn(() {}); c.insert(tid2); assert(c.length == 3, format!"3 is expected but %s"(c.length)); // Line 17 } ``` Expected behavior: It runs without errors. Actual behavior: It fails with the following message: ``` core.exception.AssertError@onlineapp.d(17): 3 is expected but 2 ---------------- ??:? _d_assert_msg [0x561d2f2e6fee] onlineapp.d:17 _Dmain [0x561d2f2d2ab5] ```
What happens is: to!string calls formatValue in std.format with a const(Tid), but hasToString in std.format fails to detect Tid's toString, because of the constness and thus uses its generic struct handler which always produces the same for all Tids. (Tid.init has a null pointer which is handled special and therefore produces a different result.) So it boils down to the following should be compilable: const(Tid) val = void; val.toString((scope const(char)[] s){}); A workaround is to define lessTid a little bit different: alias lessTid = (in Tid a, in Tid b) => (cast() a).to!string < (cast() b).to!string;
@berni44 created dlang/phobos pull request #8028 "Fix Issue 21512 - RedBlackTree!Tid treats any values as duplicated except for Tid.init" fixing this issue: - Fix Issue 21512 - RedBlackTree!Tid treats any values as duplicated except for Tid.init https://github.com/dlang/phobos/pull/8028
dlang/phobos pull request #8028 "Fix Issue 21512 - RedBlackTree!Tid treats any values as duplicated except for Tid.init" was merged into master: - 17b3745fe713b30d068145fca78b4eaab69c3e1e by berni44: Fix Issue 21512 - RedBlackTree!Tid treats any values as duplicated except for Tid.init https://github.com/dlang/phobos/pull/8028