Skip to content

Commit

Permalink
Fix Bugzilla 11725: AA.dup should return mutable AA where possible
Browse files Browse the repository at this point in the history
Since the original AA has been duplicated, it should be safe to mutate
the copy. No need to restrict the copy to be const too.
  • Loading branch information
H. S. Teoh authored and ntrel committed Oct 9, 2024
1 parent f42d5f0 commit 2e355d2
Showing 1 changed file with 32 additions and 3 deletions.
35 changes: 32 additions & 3 deletions druntime/src/object.d
Original file line number Diff line number Diff line change
Expand Up @@ -3008,15 +3008,22 @@ T rehash(T : shared Value[Key], Value, Key)(T* aa)
* Params:
* aa = The associative array.
*/
V[K] dup(T : V[K], K, V)(T aa)
auto dup(T : V[K], K, V)(T aa)
{
//pragma(msg, "K = ", K, ", V = ", V);

// Bug10720 - check whether V is copyable
static assert(is(typeof({ V v = aa[K.init]; })),
"cannot call " ~ T.stringof ~ ".dup because " ~ V.stringof ~ " is not copyable");

V[K] result;
// bug 11725: return mutable AA if possible
import core.internal.traits : Unconst;
static if (is(V : Unconst!V))
alias Result = Unconst!V[K];
else // mutable dup not possible, return const object instead.
alias Result = V[K];

Result result;

//foreach (k, ref v; aa)
// result[k] = v; // Bug13701 - won't work if V is not mutable
Expand Down Expand Up @@ -3046,7 +3053,7 @@ V[K] dup(T : V[K], K, V)(T aa)
}

/** ditto */
V[K] dup(T : V[K], K, V)(T* aa)
auto dup(T : V[K], K, V)(T* aa)
{
return (*aa).dup;
}
Expand All @@ -3060,6 +3067,28 @@ V[K] dup(T : V[K], K, V)(T* aa)
assert("k2" !in a2);
}

// bug 11725
///
@safe unittest
{
const int[string] aa = ["a": 1, "b": 2];
// Copied AA values can be mutable
int[string] bb = aa.dup;
assert(bb == ["a": 1, "b": 2]);
assert(++bb["b"] == 3);
}

version (CoreUnittest)
@safe test11725()
{
// contra case of 11725: dup'ing an AA with elements that cannot convert to
// non-const should yield const AA instead.
class C { }
const C[string] aa = [ "a": new C ];
auto bb = aa.dup;
static assert(is(typeof(bb) == const(C)[string]));
}

// this should never be made public.
private AARange _aaToRange(T: V[K], K, V)(ref T aa) pure nothrow @nogc @safe
{
Expand Down

0 comments on commit 2e355d2

Please sign in to comment.