D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 21512 - RedBlackTree!Tid treats any values as duplicated except for Tid.init
Summary: RedBlackTree!Tid treats any values as duplicated except for Tid.init
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: phobos (show other issues)
Version: D2
Hardware: x86_64 Linux
: P1 major
Assignee: No Owner
URL:
Keywords: pull
Depends on:
Blocks:
 
Reported: 2020-12-29 07:52 UTC by Tomoya Tanjo
Modified: 2021-05-02 22:48 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Tomoya Tanjo 2020-12-29 07:52:34 UTC
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]
```
Comment 1 Berni44 2021-05-02 14:22:21 UTC
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;
Comment 2 Dlang Bot 2021-05-02 16:18:43 UTC
@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
Comment 3 Dlang Bot 2021-05-02 22:48:48 UTC
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