Commit 3f81d84c by Iain Buclaw

libphobos: Merge upstream phobos bf0d0a37c

std.array.Appender and RefAppender: use .opSlice() instead of data()

Previously, Appender.data() was used to extract a slice of the Appender's array.
Now use the [] slice operator instead.  The same goes for RefAppender.

Fixes: PR d/94455

Reviewed-on: https://github.com/dlang/phobos/pull/7450
parent fc186077
99003a75a883d4ae28b276763f4d1f2a360cf1dd bf0d0a37c4c2d8762ceff7d8677e7584b770800f
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the dlang/phobos repository. merge done from the dlang/phobos repository.
...@@ -2859,10 +2859,19 @@ if (isDynamicArray!A) ...@@ -2859,10 +2859,19 @@ if (isDynamicArray!A)
} }
/** /**
* Use opSlice() from now on.
* Returns: The managed array. * Returns: The managed array.
*/ */
@property inout(ElementEncodingType!A)[] data() inout @trusted pure nothrow @property inout(ElementEncodingType!A)[] data() inout @trusted pure nothrow
{ {
return this[];
}
/**
* Returns: The managed array.
*/
@property inout(ElementEncodingType!A)[] opSlice() inout @trusted pure nothrow
{
/* @trusted operation: /* @trusted operation:
* casting Unqual!T[] to inout(T)[] * casting Unqual!T[] to inout(T)[]
*/ */
...@@ -3117,13 +3126,13 @@ if (isDynamicArray!A) ...@@ -3117,13 +3126,13 @@ if (isDynamicArray!A)
string b = "abcdefg"; string b = "abcdefg";
foreach (char c; b) foreach (char c; b)
app.put(c); app.put(c);
assert(app.data == "abcdefg"); assert(app[] == "abcdefg");
int[] a = [ 1, 2 ]; int[] a = [ 1, 2 ];
auto app2 = appender(a); auto app2 = appender(a);
app2.put(3); app2.put(3);
app2.put([ 4, 5, 6 ]); app2.put([ 4, 5, 6 ]);
assert(app2.data == [ 1, 2, 3, 4, 5, 6 ]); assert(app2[] == [ 1, 2, 3, 4, 5, 6 ]);
} }
@safe unittest @safe unittest
...@@ -3214,7 +3223,7 @@ if (isDynamicArray!A) ...@@ -3214,7 +3223,7 @@ if (isDynamicArray!A)
if (__traits(compiles, (Appender!A a) => mixin("a." ~ fn ~ "(args)"))) if (__traits(compiles, (Appender!A a) => mixin("a." ~ fn ~ "(args)")))
{ {
// we do it this way because we can't cache a void return // we do it this way because we can't cache a void return
scope(exit) *this.arr = impl.data; scope(exit) *this.arr = impl[];
mixin("return impl." ~ fn ~ "(args);"); mixin("return impl." ~ fn ~ "(args);");
} }
...@@ -3226,7 +3235,7 @@ if (isDynamicArray!A) ...@@ -3226,7 +3235,7 @@ if (isDynamicArray!A)
void opOpAssign(string op : "~", U)(U rhs) void opOpAssign(string op : "~", U)(U rhs)
if (__traits(compiles, (Appender!A a){ a.put(rhs); })) if (__traits(compiles, (Appender!A a){ a.put(rhs); }))
{ {
scope(exit) *this.arr = impl.data; scope(exit) *this.arr = impl[];
impl.put(rhs); impl.put(rhs);
} }
...@@ -3240,12 +3249,20 @@ if (isDynamicArray!A) ...@@ -3240,12 +3249,20 @@ if (isDynamicArray!A)
return impl.capacity; return impl.capacity;
} }
/** /* Use opSlice() instead.
* Returns the managed array. * Returns: the managed array.
*/ */
@property inout(ElementEncodingType!A)[] data() inout @property inout(ElementEncodingType!A)[] data() inout
{ {
return impl.data; return impl[];
}
/**
* Returns: the managed array.
*/
@property inout(ElementEncodingType!A)[] opSlice() inout
{
return impl[];
} }
} }
...@@ -3255,11 +3272,11 @@ unittest ...@@ -3255,11 +3272,11 @@ unittest
{ {
int[] a = [1, 2]; int[] a = [1, 2];
auto app2 = appender(&a); auto app2 = appender(&a);
assert(app2.data == [1, 2]); assert(app2[] == [1, 2]);
assert(a == [1, 2]); assert(a == [1, 2]);
app2 ~= 3; app2 ~= 3;
app2 ~= [4, 5, 6]; app2 ~= [4, 5, 6];
assert(app2.data == [1, 2, 3, 4, 5, 6]); assert(app2[] == [1, 2, 3, 4, 5, 6]);
assert(a == [1, 2, 3, 4, 5, 6]); assert(a == [1, 2, 3, 4, 5, 6]);
app2.reserve(5); app2.reserve(5);
...@@ -3291,33 +3308,33 @@ Appender!(E[]) appender(A : E[], E)(auto ref A array) ...@@ -3291,33 +3308,33 @@ Appender!(E[]) appender(A : E[], E)(auto ref A array)
auto app = appender!(char[])(); auto app = appender!(char[])();
string b = "abcdefg"; string b = "abcdefg";
foreach (char c; b) app.put(c); foreach (char c; b) app.put(c);
assert(app.data == "abcdefg"); assert(app[] == "abcdefg");
} }
{ {
auto app = appender!(char[])(); auto app = appender!(char[])();
string b = "abcdefg"; string b = "abcdefg";
foreach (char c; b) app ~= c; foreach (char c; b) app ~= c;
assert(app.data == "abcdefg"); assert(app[] == "abcdefg");
} }
{ {
int[] a = [ 1, 2 ]; int[] a = [ 1, 2 ];
auto app2 = appender(a); auto app2 = appender(a);
assert(app2.data == [ 1, 2 ]); assert(app2[] == [ 1, 2 ]);
app2.put(3); app2.put(3);
app2.put([ 4, 5, 6 ][]); app2.put([ 4, 5, 6 ][]);
assert(app2.data == [ 1, 2, 3, 4, 5, 6 ]); assert(app2[] == [ 1, 2, 3, 4, 5, 6 ]);
app2.put([ 7 ]); app2.put([ 7 ]);
assert(app2.data == [ 1, 2, 3, 4, 5, 6, 7 ]); assert(app2[] == [ 1, 2, 3, 4, 5, 6, 7 ]);
} }
int[] a = [ 1, 2 ]; int[] a = [ 1, 2 ];
auto app2 = appender(a); auto app2 = appender(a);
assert(app2.data == [ 1, 2 ]); assert(app2[] == [ 1, 2 ]);
app2 ~= 3; app2 ~= 3;
app2 ~= [ 4, 5, 6 ][]; app2 ~= [ 4, 5, 6 ][];
assert(app2.data == [ 1, 2, 3, 4, 5, 6 ]); assert(app2[] == [ 1, 2, 3, 4, 5, 6 ]);
app2 ~= [ 7 ]; app2 ~= [ 7 ];
assert(app2.data == [ 1, 2, 3, 4, 5, 6, 7 ]); assert(app2[] == [ 1, 2, 3, 4, 5, 6, 7 ]);
app2.reserve(5); app2.reserve(5);
assert(app2.capacity >= 5); assert(app2.capacity >= 5);
...@@ -3327,12 +3344,12 @@ Appender!(E[]) appender(A : E[], E)(auto ref A array) ...@@ -3327,12 +3344,12 @@ Appender!(E[]) appender(A : E[], E)(auto ref A array)
app2.shrinkTo(3); app2.shrinkTo(3);
} }
catch (Exception) assert(0); catch (Exception) assert(0);
assert(app2.data == [ 1, 2, 3 ]); assert(app2[] == [ 1, 2, 3 ]);
assertThrown(app2.shrinkTo(5)); assertThrown(app2.shrinkTo(5));
const app3 = app2; const app3 = app2;
assert(app3.capacity >= 3); assert(app3.capacity >= 3);
assert(app3.data == [1, 2, 3]); assert(app3[] == [1, 2, 3]);
auto app4 = appender([]); auto app4 = appender([]);
try // shrinkTo may throw try // shrinkTo may throw
...@@ -3347,29 +3364,29 @@ Appender!(E[]) appender(A : E[], E)(auto ref A array) ...@@ -3347,29 +3364,29 @@ Appender!(E[]) appender(A : E[], E)(auto ref A array)
{ {
Appender!S app5663i; Appender!S app5663i;
assertNotThrown(app5663i.put("\xE3")); assertNotThrown(app5663i.put("\xE3"));
assert(app5663i.data == "\xE3"); assert(app5663i[] == "\xE3");
Appender!S app5663c; Appender!S app5663c;
assertNotThrown(app5663c.put(cast(const(char)[])"\xE3")); assertNotThrown(app5663c.put(cast(const(char)[])"\xE3"));
assert(app5663c.data == "\xE3"); assert(app5663c[] == "\xE3");
Appender!S app5663m; Appender!S app5663m;
assertNotThrown(app5663m.put("\xE3".dup)); assertNotThrown(app5663m.put("\xE3".dup));
assert(app5663m.data == "\xE3"); assert(app5663m[] == "\xE3");
} }
// ditto for ~= // ditto for ~=
{ {
Appender!S app5663i; Appender!S app5663i;
assertNotThrown(app5663i ~= "\xE3"); assertNotThrown(app5663i ~= "\xE3");
assert(app5663i.data == "\xE3"); assert(app5663i[] == "\xE3");
Appender!S app5663c; Appender!S app5663c;
assertNotThrown(app5663c ~= cast(const(char)[])"\xE3"); assertNotThrown(app5663c ~= cast(const(char)[])"\xE3");
assert(app5663c.data == "\xE3"); assert(app5663c[] == "\xE3");
Appender!S app5663m; Appender!S app5663m;
assertNotThrown(app5663m ~= "\xE3".dup); assertNotThrown(app5663m ~= "\xE3".dup);
assert(app5663m.data == "\xE3"); assert(app5663m[] == "\xE3");
} }
} }
...@@ -3384,7 +3401,7 @@ Appender!(E[]) appender(A : E[], E)(auto ref A array) ...@@ -3384,7 +3401,7 @@ Appender!(E[]) appender(A : E[], E)(auto ref A array)
{ {
auto w = appender!(S10122[])(); auto w = appender!(S10122[])();
w.put(S10122(1)); w.put(S10122(1));
assert(w.data.length == 1 && w.data[0].val == 1); assert(w[].length == 1 && w[][0].val == 1);
}); });
} }
...@@ -3404,7 +3421,7 @@ unittest ...@@ -3404,7 +3421,7 @@ unittest
w ~= 'd'; w ~= 'd';
w ~= "ef"; w ~= "ef";
assert(w.data == "abcdef"); assert(w[] == "abcdef");
} }
@safe pure nothrow unittest @safe pure nothrow unittest
...@@ -3413,7 +3430,7 @@ unittest ...@@ -3413,7 +3430,7 @@ unittest
auto w = appender!string(); auto w = appender!string();
w.reserve(4); w.reserve(4);
cast(void) w.capacity; cast(void) w.capacity;
cast(void) w.data; cast(void) w[];
try try
{ {
wchar wc = 'a'; wchar wc = 'a';
...@@ -3427,7 +3444,7 @@ unittest ...@@ -3427,7 +3444,7 @@ unittest
auto w = appender!(int[])(); auto w = appender!(int[])();
w.reserve(4); w.reserve(4);
cast(void) w.capacity; cast(void) w.capacity;
cast(void) w.data; cast(void) w[];
w.put(10); w.put(10);
w.put([10]); w.put([10]);
w.clear(); w.clear();
...@@ -3528,7 +3545,7 @@ unittest ...@@ -3528,7 +3545,7 @@ unittest
auto app = appender!(const(E)[])(); auto app = appender!(const(E)[])();
foreach (i, e; src) foreach (i, e; src)
app.put(e); app.put(e);
return app.data; return app[];
} }
class C {} class C {}
...@@ -3554,6 +3571,8 @@ unittest ...@@ -3554,6 +3571,8 @@ unittest
@safe unittest @safe unittest
{ {
import std.algorithm.comparison : equal;
//New appender signature tests //New appender signature tests
alias mutARR = int[]; alias mutARR = int[];
alias conARR = const(int)[]; alias conARR = const(int)[];
...@@ -3563,27 +3582,40 @@ unittest ...@@ -3563,27 +3582,40 @@ unittest
conARR con; conARR con;
immARR imm; immARR imm;
{auto app = Appender!mutARR(mut);} //Always worked. Should work. Should not create a warning. auto app1 = Appender!mutARR(mut); //Always worked. Should work. Should not create a warning.
app1.put(7);
assert(equal(app1[], [7]));
static assert(!is(typeof(Appender!mutARR(con)))); //Never worked. Should not work. static assert(!is(typeof(Appender!mutARR(con)))); //Never worked. Should not work.
static assert(!is(typeof(Appender!mutARR(imm)))); //Never worked. Should not work. static assert(!is(typeof(Appender!mutARR(imm)))); //Never worked. Should not work.
{auto app = Appender!conARR(mut);} //Always worked. Should work. Should not create a warning. auto app2 = Appender!conARR(mut); //Always worked. Should work. Should not create a warning.
{auto app = Appender!conARR(con);} //Didn't work. Now works. Should not create a warning. app2.put(7);
{auto app = Appender!conARR(imm);} //Didn't work. Now works. Should not create a warning. assert(equal(app2[], [7]));
auto app3 = Appender!conARR(con); //Didn't work. Now works. Should not create a warning.
app3.put(7);
assert(equal(app3[], [7]));
auto app4 = Appender!conARR(imm); //Didn't work. Now works. Should not create a warning.
app4.put(7);
assert(equal(app4[], [7]));
//{auto app = Appender!immARR(mut);} //Worked. Will cease to work. Creates warning. //{auto app = Appender!immARR(mut);} //Worked. Will cease to work. Creates warning.
//static assert(!is(typeof(Appender!immARR(mut)))); //Worked. Will cease to work. Uncomment me after full deprecation. //static assert(!is(typeof(Appender!immARR(mut)))); //Worked. Will cease to work. Uncomment me after full deprecation.
static assert(!is(typeof(Appender!immARR(con)))); //Never worked. Should not work. static assert(!is(typeof(Appender!immARR(con)))); //Never worked. Should not work.
{auto app = Appender!immARR(imm);} //Didn't work. Now works. Should not create a warning. auto app5 = Appender!immARR(imm); //Didn't work. Now works. Should not create a warning.
app5.put(7);
assert(equal(app5[], [7]));
//Deprecated. Please uncomment and make sure this doesn't work: //Deprecated. Please uncomment and make sure this doesn't work:
//char[] cc; //char[] cc;
//static assert(!is(typeof(Appender!string(cc)))); //static assert(!is(typeof(Appender!string(cc))));
//This should always work: //This should always work:
{auto app = appender!string(null);} auto app6 = appender!string(null);
{auto app = appender!(const(char)[])(null);} assert(app6[] == null);
{auto app = appender!(char[])(null);} auto app7 = appender!(const(char)[])(null);
assert(app7[] == null);
auto app8 = appender!(char[])(null);
assert(app8[] == null);
} }
@safe unittest //Test large allocations (for GC.extend) @safe unittest //Test large allocations (for GC.extend)
...@@ -3594,7 +3626,7 @@ unittest ...@@ -3594,7 +3626,7 @@ unittest
app.reserve(1); //cover reserve on non-initialized app.reserve(1); //cover reserve on non-initialized
foreach (_; 0 .. 100_000) foreach (_; 0 .. 100_000)
app.put('a'); app.put('a');
assert(equal(app.data, 'a'.repeat(100_000))); assert(equal(app[], 'a'.repeat(100_000)));
} }
@safe unittest @safe unittest
...@@ -3610,7 +3642,9 @@ unittest ...@@ -3610,7 +3642,9 @@ unittest
@safe unittest // clear method is supported only for mutable element types @safe unittest // clear method is supported only for mutable element types
{ {
Appender!string app; Appender!string app;
app.put("foo");
static assert(!__traits(compiles, app.clear())); static assert(!__traits(compiles, app.clear()));
assert(app[] == "foo");
} }
@safe unittest @safe unittest
...@@ -3676,11 +3710,11 @@ unittest ...@@ -3676,11 +3710,11 @@ unittest
{ {
int[] a = [1, 2]; int[] a = [1, 2];
auto app2 = appender(&a); auto app2 = appender(&a);
assert(app2.data == [1, 2]); assert(app2[] == [1, 2]);
assert(a == [1, 2]); assert(a == [1, 2]);
app2 ~= 3; app2 ~= 3;
app2 ~= [4, 5, 6]; app2 ~= [4, 5, 6];
assert(app2.data == [1, 2, 3, 4, 5, 6]); assert(app2[] == [1, 2, 3, 4, 5, 6]);
assert(a == [1, 2, 3, 4, 5, 6]); assert(a == [1, 2, 3, 4, 5, 6]);
app2.reserve(5); app2.reserve(5);
...@@ -3695,7 +3729,7 @@ unittest ...@@ -3695,7 +3729,7 @@ unittest
auto app = appender(&arr); auto app = appender(&arr);
string b = "abcdefg"; string b = "abcdefg";
foreach (char c; b) app.put(c); foreach (char c; b) app.put(c);
assert(app.data == "abcdefg"); assert(app[] == "abcdefg");
assert(arr == "abcdefg"); assert(arr == "abcdefg");
} }
{ {
...@@ -3703,27 +3737,27 @@ unittest ...@@ -3703,27 +3737,27 @@ unittest
auto app = appender(&arr); auto app = appender(&arr);
string b = "abcdefg"; string b = "abcdefg";
foreach (char c; b) app ~= c; foreach (char c; b) app ~= c;
assert(app.data == "abcdefg"); assert(app[] == "abcdefg");
assert(arr == "abcdefg"); assert(arr == "abcdefg");
} }
{ {
int[] a = [ 1, 2 ]; int[] a = [ 1, 2 ];
auto app2 = appender(&a); auto app2 = appender(&a);
assert(app2.data == [ 1, 2 ]); assert(app2[] == [ 1, 2 ]);
assert(a == [ 1, 2 ]); assert(a == [ 1, 2 ]);
app2.put(3); app2.put(3);
app2.put([ 4, 5, 6 ][]); app2.put([ 4, 5, 6 ][]);
assert(app2.data == [ 1, 2, 3, 4, 5, 6 ]); assert(app2[] == [ 1, 2, 3, 4, 5, 6 ]);
assert(a == [ 1, 2, 3, 4, 5, 6 ]); assert(a == [ 1, 2, 3, 4, 5, 6 ]);
} }
int[] a = [ 1, 2 ]; int[] a = [ 1, 2 ];
auto app2 = appender(&a); auto app2 = appender(&a);
assert(app2.data == [ 1, 2 ]); assert(app2[] == [ 1, 2 ]);
assert(a == [ 1, 2 ]); assert(a == [ 1, 2 ]);
app2 ~= 3; app2 ~= 3;
app2 ~= [ 4, 5, 6 ][]; app2 ~= [ 4, 5, 6 ][];
assert(app2.data == [ 1, 2, 3, 4, 5, 6 ]); assert(app2[] == [ 1, 2, 3, 4, 5, 6 ]);
assert(a == [ 1, 2, 3, 4, 5, 6 ]); assert(a == [ 1, 2, 3, 4, 5, 6 ]);
app2.reserve(5); app2.reserve(5);
...@@ -3734,12 +3768,12 @@ unittest ...@@ -3734,12 +3768,12 @@ unittest
app2.shrinkTo(3); app2.shrinkTo(3);
} }
catch (Exception) assert(0); catch (Exception) assert(0);
assert(app2.data == [ 1, 2, 3 ]); assert(app2[] == [ 1, 2, 3 ]);
assertThrown(app2.shrinkTo(5)); assertThrown(app2.shrinkTo(5));
const app3 = app2; const app3 = app2;
assert(app3.capacity >= 3); assert(app3.capacity >= 3);
assert(app3.data == [1, 2, 3]); assert(app3[] == [1, 2, 3]);
} }
@safe unittest // issue 14605 @safe unittest // issue 14605
...@@ -3753,7 +3787,7 @@ unittest ...@@ -3753,7 +3787,7 @@ unittest
Appender!(int[]) app; Appender!(int[]) app;
short[] range = [1, 2, 3]; short[] range = [1, 2, 3];
app.put(range); app.put(range);
assert(app.data == [1, 2, 3]); assert(app[] == [1, 2, 3]);
} }
@safe unittest @safe unittest
...@@ -3766,6 +3800,6 @@ unittest ...@@ -3766,6 +3800,6 @@ unittest
put(appA, 'w'); put(appA, 'w');
s ~= 'a'; //Clobbers here? s ~= 'a'; //Clobbers here?
a ~= 'a'; //Clobbers here? a ~= 'a'; //Clobbers here?
assert(appS.data == "hellow"); assert(appS[] == "hellow");
assert(appA.data == "hellow"); assert(appA[] == "hellow");
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment