| // REQUIRED_ARGS: -preview=dip1000 -preview=in |
| |
| void main () |
| { |
| testWithAllAttributes(); |
| testForeach(); |
| } |
| |
| void testWithAllAttributes() @safe pure nothrow @nogc |
| { |
| // Used to test dtors |
| bool isTestOver = false; |
| |
| // rvalues |
| testin1(42); |
| testin2((ulong[64]).init); |
| testin3(ValueT(42)); |
| testin3(RefT(42)); |
| testin4((ValueT[64]).init); |
| testin4([RefT(42), RefT(84), RefT(126), RefT(4)]); |
| testin5(NonCopyable(true)); |
| testin6(WithPostblit(true)); |
| testin7(WithCopyCtor(true)); |
| isTestOver = false; |
| testin8(WithDtor(&isTestOver), &isTestOver); |
| isTestOver = false; |
| |
| // lvalues |
| uint a1; |
| ulong[64] a2; |
| ValueT a3; |
| ValueT[64] a4; |
| RefT a5; |
| RefT[4] a6; |
| NonCopyable a7 = NonCopyable(true); |
| WithPostblit a8; |
| WithCopyCtor a9; |
| WithDtor a10 = WithDtor(&isTestOver); |
| |
| testin1(a1); |
| testin2(a2); |
| testin3(a3); |
| testin3(a5); |
| testin4(a4); |
| testin4(a6); |
| testin5(a7); |
| testin6(a8); |
| testin7(a9); |
| isTestOver = false; |
| testin8(a10, null); |
| |
| // Arguments are all values, no `ref` needed |
| testin9(int.init); |
| testin9(char.init, ubyte.init, short.init, int.init, size_t.init); |
| // Arguments are all refs |
| testin9(a2, a4, a5, a6, a7, a8, a9, a10); |
| testin9(NonCopyable(true), WithPostblit(true), WithCopyCtor(true)); |
| // Mixed values and ref |
| testin9(char.init, ubyte.init, a2, a4, a5, a6, a7, a8, a9, a10, size_t.init); |
| |
| // With dtor |
| isTestOver = false; |
| testin10(&isTestOver, NonCopyable(true), WithPostblit(true), |
| WithCopyCtor(true), WithDtor(&isTestOver)); |
| isTestOver = true; |
| } |
| |
| void testForeach() @safe pure |
| { |
| int testCallNC (in NonCopyable k, in NonCopyable v) |
| { |
| assert(k == v); |
| return k.value - v.value; |
| } |
| |
| NonCopyable[NonCopyable] nc; |
| nc[NonCopyable(0)] = NonCopyable(0); |
| nc[NonCopyable(42)] = NonCopyable(42); |
| nc[NonCopyable(int.min)] = NonCopyable(int.min); |
| nc[NonCopyable(int.max)] = NonCopyable(int.max); |
| foreach (ref k, const ref v; nc) |
| { |
| assert(k.value == v.value); |
| assert(testCallNC(k, v) == 0); |
| } |
| assert(nc == nc); |
| assert(nc.length == 4); |
| |
| RefT[RefT] rt; |
| rt[RefT(42)] = RefT(42); |
| rt[RefT(4)] = RefT(4); |
| rt[RefT(242)] = RefT(242); |
| rt[RefT(24)] = RefT(24); |
| foreach (k, v; rt) |
| assert(k.value == v.value); |
| assert(rt == rt); |
| |
| static struct Msg |
| { |
| ubyte[3] value; |
| const(char)[] msg; |
| } |
| |
| static void testMsg (in Msg k_func, in Msg v_func) |
| { |
| assert(k_func.value == v_func.value); |
| assert(k_func.msg == v_func.msg); |
| assert(k_func == v_func); |
| } |
| |
| Msg[Msg] msg; |
| msg[Msg([1, 2, 3], "123")] = Msg([1, 2, 3], "123"); |
| msg[Msg([42, 4, 2], "4242")] = Msg([42, 4, 2], "4242"); |
| msg[Msg([242, 4, 0], "2424")] = Msg([242, 4, 0], "2424"); |
| foreach (ref k_loop, ref v_loop; msg) |
| testMsg(k_loop, v_loop); |
| } |
| |
| struct ValueT { int value; } |
| struct RefT { ulong[64] value; } |
| |
| struct NonCopyable |
| { |
| @safe pure nothrow @nogc: |
| |
| int value; |
| this(int b) { this.value = b; } |
| |
| @disable this(this); |
| @disable this(ref NonCopyable); |
| } |
| |
| struct WithPostblit |
| { |
| int value; |
| this(this) @safe pure nothrow @nogc { assert(0); } |
| } |
| |
| struct WithCopyCtor |
| { |
| @safe pure nothrow @nogc: |
| |
| int value; |
| this(int b) { this.value = b; } |
| this(ref WithCopyCtor) { assert(0); } |
| } |
| |
| struct WithDtor |
| { |
| bool* value; |
| ~this() scope @safe pure nothrow @nogc { assert(*value); } |
| } |
| |
| @safe pure nothrow @nogc: |
| |
| // By value |
| void testin1(in uint p) { static assert(!__traits(isRef, p)); } |
| // By ref because of size |
| void testin2(in ulong[64] p) { static assert(__traits(isRef, p)); } |
| // By value or ref depending on size (or structs always passed by reference) |
| void testin3(in ValueT p) { static assert(!__traits(isRef, p) || true); } |
| void testin3(in RefT p) { static assert(__traits(isRef, p)); } |
| // By ref because of size (or arrays always passed by reference) |
| void testin4(in ValueT[64] p) { static assert(__traits(isRef, p)); } |
| void testin4(in RefT[4] p) { static assert(__traits(isRef, p)); } |
| |
| // By ref because of non-copyability |
| void testin5(in NonCopyable noncopy) { static assert(__traits(isRef, noncopy)); } |
| static assert(testin5.mangleof == "_D9previewin7testin5FNaNbNiNfIKSQBe11NonCopyableZv"); // incl. `ref` |
| // By ref because of postblit |
| void testin6(in WithPostblit withpostblit) { static assert(__traits(isRef, withpostblit)); } |
| // By ref because of copy ctor |
| void testin7(in WithCopyCtor withcopy) { static assert(__traits(isRef, withcopy)); } |
| // By ref because of dtor |
| void testin8(in WithDtor withdtor, scope bool* isTestOver) |
| { |
| static assert(__traits(isRef, withdtor)); |
| if (isTestOver) |
| *isTestOver = true; |
| } |
| |
| // Allow to test various tuples (e.g. `(int, int)` and `(int, WithDtor)`) |
| // `ref` is only applied to the members which need it |
| void testin9(T...)(in T args) {} |
| void testin10(T...)(scope bool* isTestOver, in T args) |
| { |
| if (isTestOver) |
| *isTestOver = true; |
| } |