From 2e355d24456791753df1734ff327eab44402e0bb Mon Sep 17 00:00:00 2001 From: "H. S. Teoh" Date: Wed, 9 Oct 2024 11:35:57 +0100 Subject: [PATCH] Fix Bugzilla 11725: AA.dup should return mutable AA where possible 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. --- druntime/src/object.d | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/druntime/src/object.d b/druntime/src/object.d index 565f6a1b15c6..295ce1b63d67 100644 --- a/druntime/src/object.d +++ b/druntime/src/object.d @@ -3008,7 +3008,7 @@ 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); @@ -3016,7 +3016,14 @@ V[K] dup(T : V[K], K, V)(T aa) 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 @@ -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; } @@ -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 {