| /* |
| EXTRA_FILES: imports/test15777a.d imports/test15777b.d |
| TEST_OUTPUT: |
| --- |
| int |
| double |
| foobar7406(T) |
| test7406() |
| int |
| foobar7406(T) |
| int |
| test7406() |
| --- |
| */ |
| |
| extern(C) int printf(const char* fmt, ...); |
| |
| alias AliasSeq(X...) = X; |
| |
| /***************************************/ |
| |
| void test1() |
| { |
| char[] a; |
| |
| int foo() |
| { |
| printf("foo\n"); |
| a ~= "foo"; |
| return 10; |
| } |
| |
| foreach (i; 0 .. foo()) |
| { |
| printf("%d\n", i); |
| a ~= cast(char)('0' + i); |
| } |
| assert(a == "foo0123456789"); |
| |
| foreach_reverse (i; 0 .. foo()) |
| { |
| printf("%d\n", i); |
| a ~= cast(char)('0' + i); |
| } |
| assert(a == "foo0123456789foo9876543210"); |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=2411 |
| |
| struct S2411 |
| { |
| int n; |
| string s; |
| } |
| |
| void test2411() |
| { |
| S2411 s; |
| assert(s.n == 0); |
| assert(s.s == ""); |
| foreach (i, ref e; s.tupleof) |
| { |
| static if (i == 0) |
| e = 10; |
| static if (i == 1) |
| e = "str"; |
| } |
| assert(s.n == 10); |
| assert(s.s == "str"); |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=2442 |
| |
| template canForeach(T, E) |
| { |
| enum canForeach = __traits(compiles, |
| { |
| foreach(a; new T) |
| { |
| static assert(is(typeof(a) == E)); |
| } |
| }); |
| } |
| |
| void test2442() |
| { |
| struct S1 |
| { |
| int opApply(int delegate(ref const(int) v) dg) const { return 0; } |
| int opApply(int delegate(ref int v) dg) { return 0; } |
| } |
| S1 ms1; |
| const S1 cs1; |
| foreach (x; ms1) { static assert(is(typeof(x) == int)); } |
| foreach (x; cs1) { static assert(is(typeof(x) == const int)); } |
| |
| struct S2 |
| { |
| int opApply(int delegate(ref int v) dg) { return 0; } |
| int opApply(int delegate(ref long v) dg) { return 0; } |
| } |
| S2 ms2; |
| static assert(!__traits(compiles, { foreach ( x; ms2) {} })); // ambiguous |
| static assert( __traits(compiles, { foreach (int x; ms2) {} })); |
| |
| struct S3 |
| { |
| int opApply(int delegate(ref int v) dg) const { return 0; } |
| int opApply(int delegate(ref int v) dg) shared const { return 0; } |
| } |
| immutable S3 ms3; |
| static assert(!__traits(compiles, { foreach (int x; ms3) {} })); // ambiguous |
| |
| // from https://github.com/dlang/dmd/pull/120 |
| static class C |
| { |
| int opApply(int delegate(ref int v) dg) { return 0; } |
| int opApply(int delegate(ref const int v) dg) const { return 0; } |
| int opApply(int delegate(ref immutable int v) dg) immutable { return 0; } |
| int opApply(int delegate(ref shared int v) dg) shared { return 0; } |
| int opApply(int delegate(ref shared const int v) dg) shared const { return 0; } |
| } |
| static class D |
| { |
| int opApply(int delegate(ref int v) dg) const { return 0; } |
| } |
| static class E |
| { |
| int opApply(int delegate(ref int v) dg) shared const { return 0; } |
| } |
| |
| static assert( canForeach!( C , int )); |
| static assert( canForeach!( const(C) , const(int) )); |
| static assert( canForeach!( immutable(C) , immutable(int) )); |
| static assert( canForeach!( shared(C) , shared(int) )); |
| static assert( canForeach!(shared(const(C)), shared(const(int)))); |
| |
| static assert( canForeach!( D , int)); |
| static assert( canForeach!( const(D) , int)); |
| static assert( canForeach!( immutable(D) , int)); |
| static assert(!canForeach!( shared(D) , int)); |
| static assert(!canForeach!(shared(const(D)), int)); |
| |
| static assert(!canForeach!( E , int)); |
| static assert(!canForeach!( const(E) , int)); |
| static assert( canForeach!( immutable(E) , int)); |
| static assert( canForeach!( shared(E) , int)); |
| static assert( canForeach!(shared(const(E)), int)); |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=2443 |
| |
| struct S2443 |
| { |
| int[] arr; |
| int opApply(int delegate(size_t i, ref int v) dg) |
| { |
| int result = 0; |
| foreach (i, ref x; arr) |
| { |
| if ((result = dg(i, x)) != 0) |
| break; |
| } |
| return result; |
| } |
| } |
| |
| void test2443() |
| { |
| S2443 s; |
| foreach (i, ref v; s) {} |
| foreach (i, v; s) {} |
| static assert(!__traits(compiles, { foreach (ref i, ref v; s) {} })); |
| static assert(!__traits(compiles, { foreach (ref i, v; s) {} })); |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=3187 |
| |
| class Collection |
| { |
| int opApply(int delegate(ref Object) a) |
| { |
| return 0; |
| } |
| } |
| |
| Object testForeach(Collection level1, Collection level2) |
| { |
| foreach (first; level1) { |
| foreach (second; level2) |
| return second; |
| } |
| return null; |
| } |
| |
| void test3187() |
| { |
| testForeach(new Collection, new Collection); |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=4090 |
| |
| void test4090a() |
| { |
| double[10] arr = 1; |
| double tot = 0; |
| |
| static assert(!__traits(compiles, { |
| foreach (immutable ref x; arr) {} |
| })); |
| foreach (const ref x; arr) |
| { |
| static assert(is(typeof(x) == const double)); |
| tot += x; |
| } |
| foreach (immutable x; arr) |
| { |
| static assert(is(typeof(x) == immutable double)); |
| tot += x; |
| } |
| assert(tot == 1*10 + 1*10); |
| } |
| |
| void test4090b() |
| { |
| int tot = 0; |
| |
| static assert(!__traits(compiles, { |
| foreach (immutable ref x; 1..11) {} |
| })); |
| foreach (const ref x; 1..11) |
| { |
| static assert(is(typeof(x) == const int)); |
| tot += x; |
| } |
| foreach (immutable x; 1..11) |
| { |
| static assert(is(typeof(x) == immutable int)); |
| tot += x; |
| } |
| assert(tot == 55 + 55); |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=5605 |
| |
| struct MyRange |
| { |
| int theOnlyOne; |
| |
| @property bool empty() const |
| { |
| return true; |
| } |
| |
| @property ref int front() return |
| { |
| return theOnlyOne; |
| } |
| |
| void popFront() |
| {} |
| } |
| |
| struct MyCollection |
| { |
| MyRange opSlice() const |
| { |
| return MyRange(); |
| } |
| } |
| |
| void test5605() |
| { |
| auto coll = MyCollection(); |
| |
| foreach (i; coll) { // <-- compilation error |
| // ... |
| } |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7004 |
| |
| void func7004(A...)(A args) |
| { |
| foreach (i, e; args){} // OK |
| foreach (uint i, e; args){} // OK |
| foreach (size_t i, e; args){} // NG |
| } |
| void test7004() |
| { |
| func7004(1, 3.14); |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7406 |
| |
| template TypeTuple7406(T...) |
| { |
| alias T TypeTuple7406; |
| } |
| |
| template foobar7406(T) |
| { |
| enum foobar = 2; |
| } |
| |
| void test7406() |
| { |
| foreach (sym; TypeTuple7406!(int, double)) // OK |
| pragma(msg, sym.stringof); |
| |
| foreach (sym; TypeTuple7406!(foobar7406)) // OK |
| pragma(msg, sym.stringof); |
| |
| foreach (sym; TypeTuple7406!(test7406)) // OK |
| pragma(msg, sym.stringof); |
| |
| foreach (sym; TypeTuple7406!(int, foobar7406)) // Error: type int has no value |
| pragma(msg, sym.stringof); |
| |
| foreach (sym; TypeTuple7406!(int, test7406)) // Error: type int has no value |
| pragma(msg, sym.stringof); |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6659 |
| |
| void test6659() |
| { |
| static struct Iter |
| { |
| ~this() |
| { |
| ++_dtor; |
| } |
| |
| bool opCmp(ref const Iter rhs) { return _pos == rhs._pos; } |
| void opUnary(string op:"++")() { ++_pos; } |
| size_t _pos; |
| |
| static size_t _dtor; |
| } |
| |
| foreach (ref iter; Iter(0) .. Iter(10)) |
| { |
| assert(Iter._dtor == 0); |
| } |
| assert(Iter._dtor == 2); |
| |
| Iter._dtor = 0; // reset |
| |
| for (auto iter = Iter(0), limit = Iter(10); iter != limit; ++iter) |
| { |
| assert(Iter._dtor == 0); |
| } |
| assert(Iter._dtor == 2); |
| } |
| |
| void test6659a() |
| { |
| auto value = 0; |
| try |
| { |
| for ({scope(success) { assert(value == 1); value = 2;} } true; ) |
| { |
| value = 1; |
| break; |
| } |
| assert(value == 2); |
| } |
| catch (Exception e) |
| { |
| assert(0); |
| } |
| assert(value == 2); |
| } |
| |
| void test6659b() |
| { |
| auto value = 0; |
| try |
| { |
| for ({scope(failure) value = 1;} true; ) |
| { |
| throw new Exception(""); |
| } |
| assert(0); |
| } |
| catch (Exception e) |
| { |
| assert(e); |
| } |
| assert(value == 1); |
| } |
| |
| void test6659c() |
| { |
| auto value = 0; |
| try |
| { |
| for ({scope(exit) value = 1;} true; ) |
| { |
| throw new Exception(""); |
| } |
| assert(0); |
| } |
| catch (Exception e) |
| { |
| assert(e); |
| } |
| assert(value == 1); |
| } |
| |
| /***************************************/ |
| |
| // https://issues.dlang.org/show_bug.cgi?id=10221 |
| |
| void test10221() |
| { |
| // All of these should work, but most are too slow. Just check they compile. |
| foreach(char i; char.min..char.max+1) {} |
| if (0) foreach(wchar i; wchar.min..wchar.max+1) {} |
| if (0) foreach(dchar i; dchar.min..dchar.max+1) {} |
| foreach(byte i; byte.min..byte.max+1) {} |
| foreach(ubyte i; ubyte.min..ubyte.max+1) {} |
| if (0) foreach(short i; short.min..short.max+1) {} |
| if (0) foreach(ushort i; ushort.min..ushort.max+1) {} |
| if (0) foreach(int i; int.min..int.max+1U) {} |
| if (0) foreach(uint i; uint.min..uint.max+1L) {} |
| if (0) foreach(long i; long.min..long.max+1UL) {} |
| |
| foreach_reverse(char i; char.min..char.max+1) { assert(i == typeof(i).max); break; } |
| foreach_reverse(wchar i; wchar.min..wchar.max+1) { assert(i == typeof(i).max); break; } |
| foreach_reverse(dchar i; dchar.min..dchar.max+1) { assert(i == typeof(i).max); break; } |
| foreach_reverse(byte i; byte.min..byte.max+1) { assert(i == typeof(i).max); break; } |
| foreach_reverse(ubyte i; ubyte.min..ubyte.max+1) { assert(i == typeof(i).max); break; } |
| foreach_reverse(short i; short.min..short.max+1) { assert(i == typeof(i).max); break; } |
| foreach_reverse(ushort i; ushort.min..ushort.max+1) { assert(i == typeof(i).max); break; } |
| foreach_reverse(int i; int.min..int.max+1U) { assert(i == typeof(i).max); break; } |
| foreach_reverse(uint i; uint.min..uint.max+1L) { assert(i == typeof(i).max); break; } |
| foreach_reverse(long i; long.min..long.max+1UL) { assert(i == typeof(i).max); break; } |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7814 |
| |
| struct File7814 |
| { |
| ~this(){} |
| } |
| |
| struct ByLine7814 |
| { |
| File7814 file; |
| |
| // foreach interface |
| @property bool empty() const { return true; } |
| @property char[] front() { return null; } |
| void popFront(){} |
| } |
| |
| void test7814() |
| { |
| int dummy; |
| ByLine7814 f; |
| foreach (l; f) { |
| scope(failure) // 'failure' or 'success' fails, but 'exit' works |
| dummy = -1; |
| dummy = 0; |
| } |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10049 |
| |
| struct ByLine10049 |
| { |
| bool empty() { return true; } |
| string front() { return null; } |
| void popFront() {} |
| |
| ~this() {} // necessary |
| } |
| |
| void test10049() |
| { |
| ByLine10049 r; |
| foreach (line; r) |
| { |
| doNext: |
| {} |
| } |
| } |
| |
| /******************************************/ |
| |
| struct T11955(T...) { T field; alias field this; } |
| |
| alias X11955 = uint; |
| |
| struct S11955 |
| { |
| enum empty = false; |
| T11955!(uint, uint) front; |
| void popFront() {} |
| } |
| |
| void test11955() |
| { |
| foreach(X11955 i, v; S11955()) {} |
| } |
| |
| /******************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6652 |
| |
| void test6652() |
| { |
| size_t sum; |
| foreach (i; 0 .. 10) |
| sum += i++; // 0123456789 |
| assert(sum == 45); |
| |
| sum = 0; |
| foreach (ref i; 0 .. 10) |
| sum += i++; // 02468 |
| assert(sum == 20); |
| |
| sum = 0; |
| foreach_reverse (i; 0 .. 10) |
| sum += i--; // 9876543210 |
| assert(sum == 45); |
| |
| sum = 0; |
| foreach_reverse (ref i; 0 .. 10) |
| sum += i--; // 97531 |
| assert(sum == 25); |
| |
| enum ary = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; |
| sum = 0; |
| foreach (i, v; ary) |
| { |
| assert(i == v); |
| sum += i++; // 0123456789 |
| } |
| assert(sum == 45); |
| |
| sum = 0; |
| foreach (ref i, v; ary) |
| { |
| assert(i == v); |
| sum += i++; // 02468 |
| } |
| assert(sum == 20); |
| |
| sum = 0; |
| foreach_reverse (i, v; ary) |
| { |
| assert(i == v); |
| sum += i--; // 9876543210 |
| } |
| assert(sum == 45); |
| |
| sum = 0; |
| foreach_reverse (ref i, v; ary) |
| { |
| assert(i == v); |
| sum += i--; // 97531 |
| } |
| assert(sum == 25); |
| |
| static struct Iter |
| { |
| ~this() |
| { |
| ++_dtorCount; |
| } |
| |
| bool opCmp(ref const Iter rhs) |
| { |
| return _pos == rhs._pos; |
| } |
| |
| void opUnary(string op)() if(op == "++" || op == "--") |
| { |
| mixin(op ~ q{_pos;}); |
| } |
| |
| size_t _pos; |
| static size_t _dtorCount; |
| } |
| |
| Iter._dtorCount = sum = 0; |
| foreach (v; Iter(0) .. Iter(10)) |
| sum += v._pos++; // 0123456789 |
| assert(sum == 45 && Iter._dtorCount == 12); |
| |
| Iter._dtorCount = sum = 0; |
| foreach (ref v; Iter(0) .. Iter(10)) |
| sum += v._pos++; // 02468 |
| assert(sum == 20 && Iter._dtorCount == 2); |
| |
| // additional dtor calls due to unnecessary postdecrements |
| Iter._dtorCount = sum = 0; |
| foreach_reverse (v; Iter(0) .. Iter(10)) |
| sum += v._pos--; // 9876543210 |
| assert(sum == 45 && Iter._dtorCount >= 12); |
| |
| Iter._dtorCount = sum = 0; |
| foreach_reverse (ref v; Iter(0) .. Iter(10)) |
| sum += v._pos--; // 97531 |
| assert(sum == 25 && Iter._dtorCount >= 2); |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=8595 |
| |
| struct OpApply8595 |
| { |
| int opApply(int delegate(ref int) dg) |
| { |
| assert(0); |
| } |
| } |
| |
| string test8595() |
| { |
| foreach (elem; OpApply8595.init) |
| { |
| static assert(is(typeof(return) == string)); |
| } |
| assert(0); |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=9068 |
| |
| struct Foo9068 |
| { |
| static int[] destroyed; |
| int x; |
| ~this() { destroyed ~= x; } |
| } |
| |
| struct SimpleCounter9068 |
| { |
| static int destroyedCount; |
| enum int limit = 5; |
| int counter; |
| ~this() { destroyedCount++; } |
| |
| // Range primitives. |
| @property bool empty() const { return counter >= limit; } |
| @property int front() { return counter; } |
| void popFront() { counter++; } |
| } |
| |
| void test9068() |
| { |
| //---------------------------------------- |
| // There was never a bug in this case (no range). |
| int sum; |
| loop_simple: |
| foreach (i; [10, 20]) |
| { |
| sum += i; |
| break loop_simple; |
| } |
| assert(sum == 10); |
| |
| //---------------------------------------- |
| // There was a bug with loops over ranges. |
| int last = -1; |
| X: foreach (i; SimpleCounter9068()) |
| { |
| switch(i) |
| { |
| case 3: |
| break X; |
| default: |
| last = i; |
| } |
| } |
| assert(last == 2); |
| assert(SimpleCounter9068.destroyedCount == 1); |
| |
| //---------------------------------------- |
| // Simpler case: the compiler error had nothing to do with the switch. |
| last = -1; |
| loop_with_range: |
| foreach (i; SimpleCounter9068()) |
| { |
| last = i; |
| break loop_with_range; |
| } |
| assert(last == 0); |
| assert(SimpleCounter9068.destroyedCount == 2); |
| |
| //---------------------------------------- |
| // Test with destructors: the loop is implicitly wrapped into two |
| // try/finally clauses. |
| loop_with_dtors: |
| for (auto x = Foo9068(4), y = Foo9068(5); x.x != 10; ++x.x) |
| { |
| if (x.x == 8) |
| break loop_with_dtors; |
| } |
| assert(Foo9068.destroyed == [5, 8]); |
| Foo9068.destroyed = null; |
| |
| //---------------------------------------- |
| // Same with an unlabelled break. |
| for (auto x = Foo9068(4), y = Foo9068(5); x.x != 10; ++x.x) |
| { |
| if (x.x == 7) |
| break; |
| } |
| assert(Foo9068.destroyed == [5, 7]); |
| Foo9068.destroyed = null; |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=11885 |
| |
| struct Foo11885 |
| { |
| static int[] destroyed; |
| int x; |
| ~this() { destroyed ~= x; } |
| } |
| |
| struct SimpleCounter11885 |
| { |
| static int destroyedCount; |
| enum int limit = 5; |
| int counter; |
| ~this() { destroyedCount++; } |
| |
| // Range primitives. |
| @property bool empty() const { return counter >= limit; } |
| @property int front() { return counter; } |
| void popFront() { counter++; } |
| } |
| |
| void test11885() |
| { |
| //---------------------------------------- |
| // There was never a bug in this case (no range). |
| int sum; |
| loop_simple: |
| foreach (i; [10, 20]) |
| { |
| sum += i; |
| continue loop_simple; |
| } |
| assert(sum == 30); |
| |
| //---------------------------------------- |
| // There was a bug with loops over ranges. |
| int last = -1; |
| X: foreach (i; SimpleCounter11885()) |
| { |
| switch(i) |
| { |
| case 3: |
| continue X; |
| default: |
| last = i; |
| } |
| } |
| assert(last == 4); |
| assert(SimpleCounter11885.destroyedCount == 1); |
| |
| //---------------------------------------- |
| // Simpler case: the compiler error had nothing to do with the switch. |
| last = -1; |
| loop_with_range: |
| foreach (i; SimpleCounter11885()) |
| { |
| last = i; |
| continue loop_with_range; |
| } |
| assert(last == 4); |
| assert(SimpleCounter11885.destroyedCount == 2); |
| |
| //---------------------------------------- |
| // Test with destructors: the loop is implicitly wrapped into two |
| // try/finally clauses. |
| loop_with_dtors: |
| for (auto x = Foo11885(4), y = Foo11885(5); x.x != 10; ++x.x) |
| { |
| if (x.x == 8) |
| continue loop_with_dtors; |
| } |
| assert(Foo11885.destroyed == [5, 10]); |
| Foo11885.destroyed = null; |
| |
| //---------------------------------------- |
| // Same with an unlabelled continue. |
| for (auto x = Foo11885(4), y = Foo11885(5); x.x != 10; ++x.x) |
| { |
| if (x.x == 7) |
| continue; |
| } |
| assert(Foo11885.destroyed == [5, 10]); |
| Foo11885.destroyed = null; |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10475 |
| |
| void test10475a() |
| { |
| struct DirIterator |
| { |
| int _store = 42; |
| ~this() { assert(0); } |
| } |
| |
| DirIterator dirEntries() |
| { |
| throw new Exception(""); |
| } |
| |
| try |
| { |
| for (DirIterator c = dirEntries(); true; ) {} |
| assert(0); |
| } |
| catch (Exception e) |
| { |
| assert(e.next is null); |
| } |
| } |
| |
| void test10475b() |
| { |
| uint g; |
| struct S |
| { |
| uint flag; |
| ~this() { g |= flag; } |
| } |
| |
| S thrown() |
| { |
| throw new Exception(""); |
| } |
| |
| g = 0x0; |
| try |
| { |
| for (auto x = S(0x1), y = S(0x2), z = thrown(); true; ) {} |
| assert(0); |
| } |
| catch (Exception e) |
| { |
| assert(e.next is null); |
| } |
| assert(g == 0x3); |
| |
| g = 0x0; |
| try |
| { |
| for (auto x = S(0x1), y = thrown(), z = S(0x2); true; ) {} |
| assert(0); |
| } |
| catch (Exception e) |
| { |
| assert(e.next is null); |
| } |
| assert(g == 0x1); |
| |
| g = 0x0; |
| try |
| { |
| for (auto x = thrown(), y = S(0x1), z = S(0x2); true; ) {} |
| assert(0); |
| } |
| catch (Exception e) |
| { |
| assert(e.next is null); |
| } |
| assert(g == 0x0); |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=11291 |
| |
| void test11291() |
| { |
| struct Tuple(T...) |
| { |
| T field; |
| alias field this; |
| } |
| struct zip |
| { |
| string[] s1, s2; |
| |
| bool empty() { return true; } |
| auto front() { return Tuple!(string, string)(s1[0], s2[0]); } |
| void popFront() {} |
| } |
| |
| foreach (const a, const b; zip(["foo"], ["bar"])) |
| { |
| static assert(is(typeof(a) == const string)); |
| static assert(is(typeof(b) == const string)); |
| |
| static assert(!__traits(compiles, a = "something")); |
| static assert(!__traits(compiles, b = "something")); |
| } |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=12103 |
| |
| alias TypeTuple12103(TL...) = TL; |
| |
| alias Id12103(alias a) = a; |
| |
| void test12103() |
| { |
| alias fs1 = TypeTuple12103!(() => 0, () => 1); |
| foreach (i, f; fs1) |
| { |
| static assert(f() == i); |
| static assert(Id12103!f() == i); |
| assert(f() == i); |
| assert(Id12103!f() == i); |
| } |
| |
| alias fs2 = TypeTuple12103!(x=>x+0, y=>y+1); |
| foreach (i, f; fs2) |
| { |
| static assert(f(0) == i); |
| static assert(Id12103!f(0) == i); |
| assert(f(0) == i); |
| assert(Id12103!f(0) == i); |
| } |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=12739 |
| |
| struct S12739 |
| { |
| nothrow: |
| int opApply(int delegate(ref int) nothrow dg) |
| { |
| return 0; |
| } |
| } |
| |
| void test12739() nothrow |
| { |
| S12739 s; |
| foreach (e; s) {} |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=12932 |
| |
| void test12932() @nogc |
| { |
| int sum; |
| foreach (e; [1,2,3]) |
| { |
| sum += e; |
| } |
| assert(sum == 6); |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=13756 |
| |
| void test13756() |
| { |
| printf("test13756()\n"); |
| int[int] org = [1:2], aa; |
| |
| aa = org.dup; |
| foreach (v; aa) |
| { |
| static assert(is(typeof(v) == int)); |
| v = 20; |
| } |
| assert(aa == [1:2]); |
| |
| aa = org.dup; |
| foreach (ref v; aa) |
| { |
| static assert(is(typeof(v) == int)); |
| v = 20; |
| } |
| assert(aa == [1:20]); |
| |
| aa = org.dup; |
| foreach (k, v; aa) |
| { |
| static assert(is(typeof(k) == int)); |
| static assert(is(typeof(v) == int)); |
| k = 10; |
| v = 20; |
| } |
| assert(aa == [1:2]); |
| |
| aa = org.dup; |
| foreach (k, ref v; aa) |
| { |
| static assert(is(typeof(k) == int)); |
| static assert(is(typeof(v) == int)); |
| k = 10; |
| v = 20; |
| } |
| assert(aa == [1:20]); |
| |
| aa = org.dup; |
| foreach (ref k, v; aa) // NG -> OK |
| { |
| static assert(is(typeof(k) == const int)); |
| static assert(is(typeof(v) == int)); |
| static assert(!__traits(compiles, k = 10)); |
| v = 20; |
| } |
| assert(aa == [1:2]); |
| |
| aa = org.dup; |
| foreach (ref k, ref v; aa) // NG -> OK |
| { |
| static assert(is(typeof(k) == const int)); |
| static assert(is(typeof(v) == int)); |
| static assert(!__traits(compiles, k = 10)); |
| v = 20; |
| } |
| assert(aa == [1:20]); |
| |
| foreach (ref const k, v; aa) // NG -> OK, same with 'ref k' |
| { |
| static assert(is(typeof(k) == const int)); |
| } |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=14653 |
| |
| static string result14653; |
| |
| class RangeClass14653 |
| { |
| int a; |
| |
| this(T)(T...) { result14653 ~= "c"; } |
| ~this() { result14653 ~= "d"; a = -1; } |
| |
| @property bool empty() { result14653 ~= "e"; return a >= 2; } |
| @property int front() { result14653 ~= "f"; assert(a >= 0); return a; } |
| void popFront() { result14653 ~= "p"; ++a; } |
| } |
| |
| auto scoped14653(T, A...)(A args) |
| { |
| static struct Scoped(T) |
| { |
| void[__traits(classInstanceSize, T)] store; |
| T payload() { return cast(T)cast(void*)store.ptr; } |
| alias payload this; |
| |
| ~this() |
| { |
| //.destroy(payload); |
| payload.__dtor(); |
| (cast(byte[])store)[] = 0; |
| } |
| } |
| |
| Scoped!T result = void; |
| |
| //emplace!T(result.store[], args); |
| result.store[] = typeid(T).initializer[]; |
| result.payload.__ctor(args); |
| |
| return result; |
| } |
| |
| void test14653() |
| { |
| printf("test14653()\n"); |
| foreach (e; scoped14653!RangeClass14653(1)) |
| { |
| result14653 ~= "b"; |
| } |
| assert(result14653 == "cefbpefbped", result14653); |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=15777 |
| |
| template funA15777() |
| { |
| import imports.test15777a; |
| alias funA15777 = fun; |
| } |
| |
| template funB15777() |
| { |
| import imports.test15777b; |
| alias funB15777 = fun; |
| } |
| |
| template funAB15777() |
| { |
| import imports.test15777a; |
| import imports.test15777b; |
| alias funAB15777 = fun; |
| } |
| |
| void foo15777(alias tpl)() |
| { |
| alias seq = AliasSeq!(tpl!()); |
| // Make alias of 'overload set' in tuple elements |
| static assert(seq.length == 1); |
| foreach (i, n; seq) |
| { |
| static assert(__traits(identifier, seq[i]) == "fun"); |
| } |
| } |
| |
| void test15777() |
| { |
| foo15777!funA15777; |
| foo15777!funB15777; |
| foo15777!funAB15777; |
| } |
| |
| /***************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=17041 |
| |
| auto ref int[2] foo17041(A...)(auto ref A args) |
| { |
| foreach(a; args) |
| { |
| a = [12, 22]; |
| } |
| foreach(ref a; args) |
| { |
| a = [31, 41]; |
| return args[0]; |
| } |
| } |
| |
| void test17041() |
| { |
| int[2] x = [10, 20]; |
| foreach(a; AliasSeq!(x)) |
| { |
| a = [11, 21]; |
| } |
| assert(x == [10, 20]); // test by value |
| foreach(ref a; AliasSeq!(x)) |
| { |
| a = [30, 40]; |
| } |
| assert(x == [30, 40]); // test by ref value |
| |
| assert(foo17041(x) == [31, 41]); // test lvalue |
| assert(x == [31, 41]); |
| assert(foo17041(cast(int[2]) [10, 20]) == [31, 41]); // test rvalue |
| } |
| |
| /***************************************/ |
| |
| int main() |
| { |
| test1(); |
| test2411(); |
| test2442(); |
| test2443(); |
| test3187(); |
| test4090a(); |
| test4090b(); |
| test5605(); |
| test7004(); |
| test10221(); |
| test7406(); |
| test6659(); |
| test6659a(); |
| test6659b(); |
| test6659c(); |
| test7814(); |
| test6652(); |
| test9068(); |
| test11885(); |
| test10475a(); |
| test10475b(); |
| test11291(); |
| test12103(); |
| test12739(); |
| test12932(); |
| test13756(); |
| test14653(); |
| test17041(); |
| |
| printf("Success\n"); |
| return 0; |
| } |