| /* |
| RUN_OUTPUT: |
| --- |
| Success |
| --- |
| */ |
| extern(C) int printf(const char*, ...); |
| |
| /**********************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7511 |
| |
| struct S7511(T) |
| { |
| // this is a pure function for T==int |
| T foo(T x) |
| { |
| return 2 * x; |
| } |
| } |
| |
| void test7511a() pure |
| { |
| S7511!int s; |
| s.foo(2); // error -> OK |
| } |
| |
| /**********************************/ |
| // certain case - wrapper range |
| |
| //import std.range; |
| @property bool empty(T)(in T[] a) { return !a.length; } |
| @property ref T front(T)(T[] a) { return a[0]; } |
| void popFront(T)(ref T[] a) { a = a[1 .. $]; } |
| |
| struct S(T) |
| { |
| int foo() |
| { |
| auto t = T(); |
| return t.bar(); |
| } |
| } |
| |
| struct Wrap(R) |
| { |
| R original; |
| this(T : R)(T t) { original = t; } |
| this(A...)(A args) { original = R(args); } |
| @property auto empty() { return original.empty; } |
| @property auto front() { return original.front; } |
| void popFront() { original.popFront(); } |
| } |
| |
| void test7511b() pure @safe |
| { |
| static struct Iota |
| { |
| size_t curr; |
| size_t max; |
| @property bool empty() pure @safe { return curr == max; } |
| @property size_t front() pure @safe { return curr; } |
| void popFront() pure @safe { ++curr; } |
| } |
| { |
| auto a = Iota(0, 3); |
| size_t i = 0; |
| foreach (e; a) { assert(e == i++); } // OK |
| } |
| { |
| auto a = Wrap!(int[])([0,1,2]); |
| size_t i = 0; |
| foreach (e; a) { assert(e == i++); } // errors! |
| } |
| { |
| auto a = Wrap!Iota(0, 3); |
| size_t i = 0; |
| foreach (e; a) { assert(e == i++); } // errors! |
| } |
| } |
| |
| /**********************************/ |
| // with attribute inheritance |
| |
| struct X |
| { |
| static int bar() pure nothrow @safe |
| { |
| return 1; |
| } |
| } |
| |
| class Class(T) |
| { |
| int foo() |
| { // inferred to pure nothrow @safe |
| return T.bar(); |
| } |
| } |
| |
| alias Class!X C; |
| |
| class D : C |
| { |
| override int foo() |
| { // inherits attributes from Class!X.foo |
| return 2; |
| } |
| } |
| |
| void test7511c() pure nothrow @safe |
| { |
| // Disabled for Bigzilla 9952 |
| /+ |
| assert((new C()).foo() == 1); |
| assert((new D()).foo() == 2); |
| static assert(typeof(&C.init.foo).stringof == "int delegate() pure nothrow @safe"); |
| static assert(typeof(&D.init.foo).stringof == "int delegate() pure nothrow @safe"); |
| +/ |
| } |
| |
| /**********************************/ |
| // curiously recurring template pattern (CRTP) |
| |
| class BX(T, bool mutual) |
| { |
| int foo() |
| { |
| static if (mutual) |
| return (cast(T)this).foo(); |
| else |
| return 0; |
| } |
| } |
| |
| class D1 : BX!(D1, true) |
| { |
| alias typeof(super) B; |
| int val; |
| this(int n) { val = n; } |
| override int foo() { return val; } |
| } |
| class D2 : BX!(D2, false) |
| { |
| alias typeof(super) B; |
| int val; |
| this(int n) { val = n; } |
| override int foo() { return val; } |
| } |
| class D3 : BX!(D3, true) |
| { |
| alias typeof(super) B; |
| int val; |
| this(int n) { val = n; } |
| override int foo() pure nothrow { return val; } |
| } |
| class D4 : BX!(D4, false) |
| { |
| alias typeof(super) B; |
| int val; |
| this(int n) { val = n; } |
| override int foo() pure nothrow { return val; } |
| } |
| |
| void test7511d() |
| { |
| // Disabled for Bigzilla 9952 |
| /+ |
| // mutual dependent and attribute inference impure, un-@safe, and may throw is default. |
| auto d1 = new D1(10); |
| static assert(is(typeof(&d1.B.foo) == int function())); |
| static assert(is(typeof(&d1.foo) == int delegate())); |
| assert(d1.foo() == 10); |
| |
| // no mutual dependent. |
| auto d2 = new D2(10); |
| static assert(is(typeof(&d2.B.foo) == int function() pure nothrow @safe)); |
| static assert(is(typeof(&d2 .foo) == int delegate() pure nothrow @safe)); |
| assert(d2.foo() == 10); |
| |
| // mutual dependent with explicit attribute specification. |
| auto d3 = new D3(10); |
| static assert(is(typeof(&d3.B.foo) == int function() pure nothrow)); |
| static assert(is(typeof(&d3 .foo) == int delegate() pure nothrow)); |
| assert(d3.foo() == 10); |
| |
| // no mutual dependent with explicit attribute specification. |
| auto d4 = new D4(10); |
| static assert(is(typeof(&d4.B.foo) == int function() pure nothrow @safe)); |
| static assert(is(typeof(&d4 .foo) == int delegate() pure nothrow @safe)); |
| assert(d4.foo() == 10); |
| +/ |
| } |
| |
| /**********************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=9952 |
| |
| @system void writeln9952(int) {} // impure throwable |
| |
| class C9952(T) |
| { |
| T foo() |
| { |
| return 2; |
| } |
| } |
| |
| class D9952 : C9952!int |
| { |
| override int foo() |
| { |
| writeln9952(super.foo()); |
| return 3; |
| } |
| } |
| |
| void test9952() |
| { |
| static assert(typeof(&C9952!int.init.foo).stringof == "int delegate()"); |
| static assert(typeof(&D9952 .init.foo).stringof == "int delegate()"); |
| } |
| |
| /**********************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10373 |
| |
| template isMutable10373(T) |
| { |
| enum isMutable10373 = !is(T == const) && !is(T == immutable) && !is(T == inout); |
| } |
| |
| struct Test10373a(T, int N = 0) |
| { |
| static if (N == 0) T[ ] mBuffer; |
| else T[N] mBuffer; |
| |
| static if (is(T == class)) |
| {} |
| else |
| { |
| T* at_(size_t n) { return &mBuffer[n]; } |
| |
| static if (is(typeof(*at_(0) = T.init))) |
| { |
| T opIndexAssign(T v, size_t i) |
| { |
| return (*at_(i) = v); |
| } |
| } |
| } |
| } |
| struct Test10373b(T, int N = 0) |
| { |
| static if (is(T == class)) |
| {} |
| else |
| { |
| T* at_(size_t n) { return &mBuffer[n]; } |
| |
| static if (is(typeof(*at_(0) = T.init))) |
| { |
| T opIndexAssign(T v, size_t i) |
| { |
| return (*at_(i) = v); |
| } |
| } |
| } |
| |
| static if (N == 0) T[ ] mBuffer; |
| else T[N] mBuffer; |
| } |
| struct Test10373c(T, int N = 0) |
| { |
| static if (is(T == class)) |
| {} |
| else |
| { |
| T* at_(size_t n) { return &mBuffer[n]; } |
| |
| static if (isMutable10373!T) |
| { |
| T opIndexAssign(T v, size_t i) |
| { |
| return (*at_(i) = v); |
| } |
| } |
| } |
| |
| static if (N == 0) T[ ] mBuffer; |
| else T[N] mBuffer; |
| } |
| |
| void test10373() |
| { |
| static assert(is(Test10373a!(int, 2))); |
| static assert(is(Test10373b!(int, 2))); |
| static assert(is(Test10373c!(int, 2))); |
| |
| Test10373a!(int, 2) testa; // dmd2.062:OK dmd2.063:OK |
| Test10373b!(int, 2) testb; // dmd2.062:OK dmd2.063:NG |
| Test10373c!(int, 2) testc; // dmd2.062:OK dmd2.063:OK |
| } |
| |
| /**********************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10329 |
| |
| auto foo10329(T)(T arg) |
| { |
| auto bar() |
| { |
| return arg; |
| } |
| static assert(is(typeof(&bar) == T delegate() pure nothrow @nogc @safe)); |
| return bar(); |
| } |
| |
| auto make10329(T)(T arg) |
| { |
| struct S |
| { |
| auto front() { return T.init; } |
| } |
| S s; |
| static assert(is(typeof(&s.front) == T delegate() pure nothrow @nogc @safe)); |
| return s; |
| } |
| |
| void test10329() pure nothrow @safe |
| { |
| assert(foo10329(1) == 1); |
| |
| auto s = make10329(1); |
| assert(s.front() == 0); |
| } |
| |
| /**********************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=11896 |
| |
| class Foo11896a(T = int) |
| { |
| static if (!__traits(isVirtualMethod, zoo)) {} else { Undefined x; } |
| |
| static void bar() {} |
| static void bar(Foo11896a foo) {} |
| |
| static void zoo() |
| { |
| bar(new Foo11896a); |
| } |
| } |
| Foo11896a!(int) baz11896a; |
| |
| // ---- |
| |
| Frop11896b!(int) frop11896b; |
| |
| mixin template baz11896b() |
| { |
| public void bar11896b() {} |
| } |
| |
| mixin baz11896b; |
| |
| class Foo11896b(T) |
| { |
| static if (! __traits(isVirtualMethod, zoo)) {} |
| |
| static void zoo() |
| { |
| bar11896b(); |
| } |
| } |
| |
| class Frop11896b(T) : Foo11896b!T {} |
| |
| // ---- |
| |
| static bool flag11896c = false; |
| |
| class Bar11896c {} |
| |
| class Foo11896c(T = Bar11896c) |
| { |
| static if (! __traits(isVirtualMethod, foo)) {} |
| alias Foo11896c!(T) this_type; |
| this() |
| { |
| flag11896c = true; |
| } |
| static public this_type foo() |
| { |
| auto c = new this_type(); |
| return flag11896c ? c : null; |
| } |
| } |
| |
| void test11896c() |
| { |
| alias Foo11896c!Bar11896c FooBar; |
| assert(FooBar.foo() !is null); |
| } |
| |
| /**********************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=12392 |
| |
| void f12392(T)() {} |
| alias fa12392 = f12392; |
| |
| void test12392() pure nothrow @safe |
| { |
| fa12392!int(); |
| } |
| |
| /**********************************/ |
| |
| int main() |
| { |
| test7511a(); |
| test7511b(); |
| test7511c(); |
| test7511d(); |
| test9952(); |
| test10373(); |
| test10329(); |
| test11896c(); |
| |
| printf("Success\n"); |
| return 0; |
| } |