Skip to content

Commit 913ef46

Browse files
authored
Fix bugzilla issue 24809: In some cases, stable sort assigns to unininitialized elements (#9057)
1 parent 706d971 commit 913ef46

File tree

1 file changed

+71
-2
lines changed

1 file changed

+71
-2
lines changed

std/algorithm/sorting.d

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2625,11 +2625,21 @@ private template TimSortImpl(alias pred, R)
26252625
// can't use `temp.length` if there's no default constructor
26262626
static if (__traits(compiles, { T defaultConstructed; cast(void) defaultConstructed; }))
26272627
{
2628-
if (__ctfe) temp.length = newSize;
2629-
else temp = () @trusted { return uninitializedArray!(T[])(newSize); }();
2628+
2629+
static if (hasElaborateAssign!T)
2630+
temp.length = newSize;
2631+
else
2632+
{
2633+
if (__ctfe) temp.length = newSize;
2634+
else temp = () @trusted { return uninitializedArray!(T[])(newSize); }();
2635+
}
26302636
}
26312637
else
26322638
{
2639+
static assert(!hasElaborateAssign!T,
2640+
"Structs which have opAssign but cannot be default-initialized " ~
2641+
"do not currently work with stable sort: " ~
2642+
"https://issues.dlang.org/show_bug.cgi?id=24810");
26332643
temp = () @trusted { return uninitializedArray!(T[])(newSize); }();
26342644
}
26352645
}
@@ -3093,6 +3103,65 @@ private template TimSortImpl(alias pred, R)
30933103
array.sort!((a, b) => false, SwapStrategy.stable);
30943104
}
30953105

3106+
// https://issues.dlang.org/show_bug.cgi?id=24809
3107+
@safe unittest
3108+
{
3109+
static struct E
3110+
{
3111+
int value;
3112+
int valid = 42;
3113+
3114+
~this()
3115+
{
3116+
assert(valid == 42);
3117+
}
3118+
}
3119+
3120+
import std.array : array;
3121+
import std.range : chain, only, repeat;
3122+
auto arr = chain(repeat(E(41), 18),
3123+
only(E(39)),
3124+
repeat(E(41), 16),
3125+
only(E(1)),
3126+
repeat(E(42), 33),
3127+
only(E(33)),
3128+
repeat(E(42), 16),
3129+
repeat(E(43), 27),
3130+
only(E(33)),
3131+
repeat(E(43), 34),
3132+
only(E(34)),
3133+
only(E(43)),
3134+
only(E(63)),
3135+
repeat(E(44), 42),
3136+
only(E(27)),
3137+
repeat(E(44), 11),
3138+
repeat(E(45), 64),
3139+
repeat(E(46), 3),
3140+
only(E(11)),
3141+
repeat(E(46), 7),
3142+
only(E(4)),
3143+
repeat(E(46), 34),
3144+
only(E(36)),
3145+
repeat(E(46), 17),
3146+
repeat(E(47), 36),
3147+
only(E(39)),
3148+
repeat(E(47), 26),
3149+
repeat(E(48), 17),
3150+
only(E(21)),
3151+
repeat(E(48), 5),
3152+
only(E(39)),
3153+
repeat(E(48), 14),
3154+
only(E(58)),
3155+
repeat(E(48), 24),
3156+
repeat(E(49), 13),
3157+
only(E(40)),
3158+
repeat(E(49), 38),
3159+
only(E(18)),
3160+
repeat(E(49), 11),
3161+
repeat(E(50), 6)).array();
3162+
3163+
arr.sort!((a, b) => a.value < b.value, SwapStrategy.stable)();
3164+
}
30963165

30973166
// schwartzSort
30983167
/**

0 commit comments

Comments
 (0)