| /* |
| TEST_OUTPUT: |
| --- |
| int delegate() pure nothrow @nogc @safe delegate() pure nothrow @nogc @safe delegate() pure nothrow @safe |
| int delegate() pure nothrow @nogc @safe delegate() pure nothrow @nogc @safe delegate() pure nothrow @safe |
| int |
| int |
| int[] |
| int delegate() pure nothrow @nogc @safe function() pure nothrow @safe |
| --- |
| |
| RUN_OUTPUT: |
| --- |
| Success |
| --- |
| */ |
| import core.vararg; |
| |
| extern (C) int printf(const char*, ...); |
| |
| /***************************************************/ |
| // lambda syntax check |
| |
| auto una(alias dg)(int n) |
| { |
| return dg(n); |
| } |
| auto bin(alias dg)(int n, int m) |
| { |
| return dg(n, m); |
| } |
| void test1() |
| { |
| assert(una!( a => a*2 )(2) == 4); |
| assert(una!( ( a) => a*2 )(2) == 4); |
| assert(una!( (int a) => a*2 )(2) == 4); |
| assert(una!( ( a){ return a*2; } )(2) == 4); |
| assert(una!( function ( a){ return a*2; } )(2) == 4); |
| assert(una!( function int( a){ return a*2; } )(2) == 4); |
| assert(una!( function (int a){ return a*2; } )(2) == 4); |
| assert(una!( function int(int a){ return a*2; } )(2) == 4); |
| assert(una!( delegate ( a){ return a*2; } )(2) == 4); |
| assert(una!( delegate int( a){ return a*2; } )(2) == 4); |
| assert(una!( delegate (int a){ return a*2; } )(2) == 4); |
| assert(una!( delegate int(int a){ return a*2; } )(2) == 4); |
| |
| // partial parameter specialization syntax |
| assert(bin!( ( a, b) => a*2+b )(2,1) == 5); |
| assert(bin!( (int a, b) => a*2+b )(2,1) == 5); |
| assert(bin!( ( a, int b) => a*2+b )(2,1) == 5); |
| assert(bin!( (int a, int b) => a*2+b )(2,1) == 5); |
| assert(bin!( ( a, b){ return a*2+b; } )(2,1) == 5); |
| assert(bin!( (int a, b){ return a*2+b; } )(2,1) == 5); |
| assert(bin!( ( a, int b){ return a*2+b; } )(2,1) == 5); |
| assert(bin!( (int a, int b){ return a*2+b; } )(2,1) == 5); |
| assert(bin!( function ( a, b){ return a*2+b; } )(2,1) == 5); |
| assert(bin!( function (int a, b){ return a*2+b; } )(2,1) == 5); |
| assert(bin!( function ( a, int b){ return a*2+b; } )(2,1) == 5); |
| assert(bin!( function (int a, int b){ return a*2+b; } )(2,1) == 5); |
| assert(bin!( function int( a, b){ return a*2+b; } )(2,1) == 5); |
| assert(bin!( function int(int a, b){ return a*2+b; } )(2,1) == 5); |
| assert(bin!( function int( a, int b){ return a*2+b; } )(2,1) == 5); |
| assert(bin!( function int(int a, int b){ return a*2+b; } )(2,1) == 5); |
| assert(bin!( delegate ( a, b){ return a*2+b; } )(2,1) == 5); |
| assert(bin!( delegate (int a, b){ return a*2+b; } )(2,1) == 5); |
| assert(bin!( delegate ( a, int b){ return a*2+b; } )(2,1) == 5); |
| assert(bin!( delegate (int a, int b){ return a*2+b; } )(2,1) == 5); |
| assert(bin!( delegate int( a, b){ return a*2+b; } )(2,1) == 5); |
| assert(bin!( delegate int(int a, b){ return a*2+b; } )(2,1) == 5); |
| assert(bin!( delegate int( a, int b){ return a*2+b; } )(2,1) == 5); |
| assert(bin!( delegate int(int a, int b){ return a*2+b; } )(2,1) == 5); |
| } |
| |
| /***************************************************/ |
| // on initializer |
| |
| void test2() |
| { |
| // explicit typed binding ignite parameter types inference |
| int function(int) fn1 = a => a*2; assert(fn1(2) == 4); |
| int function(int) fn2 = ( a){ return a*2; }; assert(fn2(2) == 4); |
| int function(int) fn3 = function ( a){ return a*2; }; assert(fn3(2) == 4); |
| int function(int) fn4 = function int( a){ return a*2; }; assert(fn4(2) == 4); |
| int function(int) fn5 = function (int a){ return a*2; }; assert(fn5(2) == 4); |
| int function(int) fn6 = function int(int a){ return a*2; }; assert(fn6(2) == 4); |
| int delegate(int) dg1 = a => a*2; assert(dg1(2) == 4); |
| int delegate(int) dg2 = ( a){ return a*2; }; assert(dg2(2) == 4); |
| int delegate(int) dg3 = delegate ( a){ return a*2; }; assert(dg3(2) == 4); |
| int delegate(int) dg4 = delegate int( a){ return a*2; }; assert(dg4(2) == 4); |
| int delegate(int) dg5 = delegate (int a){ return a*2; }; assert(dg5(2) == 4); |
| int delegate(int) dg6 = delegate int(int a){ return a*2; }; assert(dg6(2) == 4); |
| |
| // function/delegate mismatching always raises an error |
| static assert(!__traits(compiles, { int function(int) xfg3 = delegate ( a){ return a*2; }; })); |
| static assert(!__traits(compiles, { int function(int) xfg4 = delegate int( a){ return a*2; }; })); |
| static assert(!__traits(compiles, { int function(int) xfg5 = delegate (int a){ return a*2; }; })); |
| static assert(!__traits(compiles, { int function(int) xfg6 = delegate int(int a){ return a*2; }; })); |
| static assert(!__traits(compiles, { int delegate(int) xdn3 = function ( a){ return a*2; }; })); |
| static assert(!__traits(compiles, { int delegate(int) xdn4 = function int( a){ return a*2; }; })); |
| static assert(!__traits(compiles, { int delegate(int) xdn5 = function (int a){ return a*2; }; })); |
| static assert(!__traits(compiles, { int delegate(int) xdn6 = function int(int a){ return a*2; }; })); |
| |
| // auto binding requires explicit parameter types at least |
| static assert(!__traits(compiles, { auto afn1 = a => a*2; })); |
| static assert(!__traits(compiles, { auto afn2 = ( a){ return a*2; }; })); |
| static assert(!__traits(compiles, { auto afn3 = function ( a){ return a*2; }; })); |
| static assert(!__traits(compiles, { auto afn4 = function int( a){ return a*2; }; })); |
| static assert(!__traits(compiles, { auto adg3 = delegate ( a){ return a*2; }; })); |
| static assert(!__traits(compiles, { auto adg4 = delegate int( a){ return a*2; }; })); |
| auto afn5 = function (int a){ return a*2; }; assert(afn5(2) == 4); |
| auto afn6 = function int(int a){ return a*2; }; assert(afn6(2) == 4); |
| auto adg5 = delegate (int a){ return a*2; }; assert(adg5(2) == 4); |
| auto adg6 = delegate int(int a){ return a*2; }; assert(adg6(2) == 4); |
| |
| // partial specialized lambda |
| string delegate(int, string) dg = |
| (n, string s){ |
| string r = ""; |
| foreach (_; 0..n) r~=s; |
| return r; |
| }; |
| assert(dg(2, "str") == "strstr"); |
| } |
| |
| /***************************************************/ |
| // on return statement |
| |
| void test3() |
| { |
| // inference matching system is same as on initializer |
| int delegate(int) mul(int x) |
| { |
| return a => a * x; |
| } |
| assert(mul(5)(2) == 10); |
| } |
| |
| /***************************************************/ |
| // on function arguments |
| |
| auto foo4(int delegate(int) dg) { return dg(10); } |
| auto foo4(int delegate(int, int) dg) { return dg(10, 20); } |
| |
| void nbar4fp(void function(int) fp) { } |
| void nbar4dg(void delegate(int) dg) { } |
| void tbar4fp(T,R)(R function(T) dg) { static assert(is(typeof(dg) == void function(int))); } |
| void tbar4dg(T,R)(R delegate(T) dg) { static assert(is(typeof(dg) == void delegate(int))); } |
| |
| auto nbaz4(void function() fp) { return 1; } |
| auto nbaz4(void delegate() dg) { return 2; } |
| auto tbaz4(R)(R function() dg) { static assert(is(R == void)); return 1; } |
| auto tbaz4(R)(R delegate() dg) { static assert(is(R == void)); return 2; } |
| |
| auto thoo4(T)(T lambda){ return lambda; } |
| |
| void tfun4a()(int function(int) a){} |
| void tfun4b(T)(T function(T) a){} |
| void tfun4c(T)(T f){} |
| |
| void test4() |
| { |
| int v; |
| static void sfoo() {} |
| void nfoo() {} |
| |
| // parameter type inference + overload resolution |
| assert(foo4((a) => a * 2) == 20); |
| assert(foo4((a,b) => a * 2 + b) == 40); |
| |
| // function/delegate inference |
| nbar4fp((int x){ }); |
| nbar4dg((int x){ }); |
| tbar4fp((int x){ }); |
| tbar4dg((int x){ }); |
| |
| // function/delegate inference + overload resolution |
| assert(nbaz4({ }) == 1); |
| assert(nbaz4({ v = 1; }) == 2); |
| assert(nbaz4({ sfoo(); }) == 1); // Bugzilla 8836 |
| assert(nbaz4({ nfoo(); }) == 2); |
| |
| assert(tbaz4({ }) == 1); |
| assert(tbaz4({ v = 1; }) == 2); |
| assert(tbaz4({ sfoo(); }) == 1); |
| assert(tbaz4({ nfoo(); }) == 2); |
| |
| // template function deduction |
| static assert(is(typeof(thoo4({ })) : void function())); |
| static assert(is(typeof(thoo4({ v = 1; })) : void delegate())); |
| |
| tfun4a(a => a); |
| static assert(!__traits(compiles, { tfun4b(a => a); })); |
| static assert(!__traits(compiles, { tfun4c(a => a); })); |
| } |
| |
| void fsvarg4(int function(int)[] a...){} |
| void fcvarg4(int dummy, ...){} |
| |
| void tsvarg4a()(int function(int)[] a...){} |
| void tsvarg4b(T)(T function(T)[] a...){} |
| void tsvarg4c(T)(T [] a...){} |
| void tcvarg4()(int dummy, ...){} |
| |
| void test4v() |
| { |
| fsvarg4(function(int a){ return a; }); // OK |
| fsvarg4(a => a); // OK |
| |
| fcvarg4(0, function(int a){ return a; }); // OK |
| static assert(!__traits(compiles, { fcvarg4(0, a => a); })); |
| |
| tsvarg4a(function(int a){ return a; }); // OK |
| tsvarg4b(function(int a){ return a; }); // OK |
| tsvarg4c(function(int a){ return a; }); // OK |
| tsvarg4a(a => a); |
| static assert(!__traits(compiles, { tsvarg4b(a => a); })); |
| static assert(!__traits(compiles, { tsvarg4c(a => a); })); |
| |
| tcvarg4(0, function(int a){ return a; }); // OK |
| static assert(!__traits(compiles, { tcvarg4(0, a => a); })); |
| } |
| |
| // A lambda in function default argument should be deduced to delegate, by the |
| // preparation inferType call in TypeFunction.semantic. |
| void test4_findRoot(scope bool delegate(real lo, real hi) tolerance = (real a, real b) => false) |
| {} |
| |
| /***************************************************/ |
| // on CallExp::e1 |
| |
| void test5() |
| { |
| assert((a => a*2)(10) == 20); |
| assert(( a, s){ return s~s; }(10, "str") == "strstr"); |
| assert((int a, s){ return s~s; }(10, "str") == "strstr"); |
| assert(( a, string s){ return s~s; }(10, "str") == "strstr"); |
| assert((int a, string s){ return s~s; }(10, "str") == "strstr"); |
| } |
| |
| /***************************************************/ |
| // escape check to nested function symbols |
| |
| void checkNestedRef(alias dg)(bool isnested) |
| { |
| static if (is(typeof(dg) == delegate)) |
| enum isNested = true; |
| else static if ((is(typeof(dg) PF == F*, F) && is(F == function))) |
| enum isNested = false; |
| else |
| static assert(0); |
| |
| assert(isnested == isNested); |
| dg(); |
| } |
| |
| void freeFunc(){} |
| |
| void test6() |
| { |
| static void localFunc(){} |
| void nestedLocalFunc(){} |
| |
| checkNestedRef!({ })(false); |
| |
| checkNestedRef!({ freeFunc(); })(false); |
| checkNestedRef!({ localFunc(); })(false); |
| checkNestedRef!({ nestedLocalFunc(); })(true); |
| checkNestedRef!({ void inner(){} inner(); })(false); |
| |
| checkNestedRef!({ auto f = &freeFunc; })(false); |
| checkNestedRef!({ auto f = &localFunc; })(false); |
| checkNestedRef!({ auto f = &nestedLocalFunc; })(true); |
| checkNestedRef!({ void inner(){} auto f = &inner; })(false); |
| } |
| |
| /***************************************************/ |
| // on AssignExp::e2 |
| |
| void test7() |
| { |
| int function(int) fp; |
| fp = a => a; |
| fp = (int a) => a; |
| fp = function(int a) => a; |
| fp = function int(int a) => a; |
| static assert(!__traits(compiles, { fp = delegate(int a) => a; })); |
| static assert(!__traits(compiles, { fp = delegate int(int a) => a; })); |
| |
| int delegate(int) dg; |
| dg = a => a; |
| dg = (int a) => a; |
| dg = delegate(int a) => a; |
| dg = delegate int(int a) => a; |
| static assert(!__traits(compiles, { dg = function(int a) => a; })); |
| static assert(!__traits(compiles, { dg = function int(int a) => a; })); |
| } |
| |
| /***************************************************/ |
| // on StructLiteralExp::elements |
| |
| void test8() |
| { |
| struct S |
| { |
| int function(int) fp; |
| } |
| auto s1 = S(a => a); |
| static assert(!__traits(compiles, { auto s2 = S((a, b) => a); })); |
| } |
| |
| /***************************************************/ |
| // on concat operation |
| |
| void test9() |
| { |
| int function(int)[] a2; |
| a2 ~= x => x; |
| } |
| |
| /***************************************************/ |
| // on associative array key |
| |
| void test10() |
| { |
| int[int function()] aa; |
| assert(!aa.remove(() => 1)); |
| |
| int[int function(int)] aa2; |
| assert(!aa2.remove(x => 1)); |
| } |
| |
| /***************************************************/ |
| // on common type deduction |
| |
| void test11() |
| { |
| auto a1 = [x => x, (int x) => x * 2]; |
| static assert(is(typeof(a1[0]) == int function(int) pure @safe nothrow @nogc)); |
| assert(a1[0](10) == 10); |
| assert(a1[1](10) == 20); |
| |
| //int n = 10; |
| //auto a2 = [x => n, (int x) => x * 2]; |
| //static assert(is(typeof(a2[0]) == int delegate(int) @safe nothrow)); |
| //assert(a2[0](99) == 10); |
| //assert(a2[1](10) == 20); |
| |
| int function(int) fp = true ? (x => x) : (x => x*2); |
| assert(fp(10) == 10); |
| |
| int m = 10; |
| int delegate(int) dg = true ? (x => x) : (x => m*2); |
| assert(dg(10) == 10); |
| } |
| |
| /***************************************************/ |
| // 3235 |
| |
| void test3235() |
| { |
| // from TDPL |
| auto f = (int i) {}; |
| static if (is(typeof(f) _ == F*, F) && is(F == function)) |
| {} else static assert(0); |
| } |
| |
| /***************************************************/ |
| // 6714 |
| |
| void foo6714x(int function (int, int) a){} |
| void bar6714x(int delegate (int, int) a){} |
| |
| int bar6714y(double delegate(int, int) a){ return 1; } |
| int bar6714y( int delegate(int, int) a){ return 2; } |
| |
| void test6714() |
| { |
| foo6714x((a, b) { return a + b; }); |
| bar6714x((a, b) { return a + b; }); |
| |
| assert(bar6714y((a, b){ return 1.0; }) == 1); |
| assert(bar6714y((a, b){ return 1.0f; }) == 1); |
| assert(bar6714y((a, b){ return a; }) == 2); |
| } |
| |
| /***************************************************/ |
| // 7193 |
| |
| void test7193() |
| { |
| static assert(!__traits(compiles, { |
| delete a => a; |
| })); |
| } |
| |
| /***************************************************/ |
| // 7207 : on CastExp |
| |
| void test7202() |
| { |
| auto dg = cast(int function(int))(a => a); |
| assert(dg(10) == 10); |
| } |
| |
| /***************************************************/ |
| // 7288 |
| |
| void test7288() |
| { |
| // 7288 -> OK |
| auto foo() |
| { |
| int x; |
| return () => { return x; }; |
| } |
| pragma(msg, typeof(&foo)); |
| alias int delegate() pure nothrow @nogc @safe delegate() pure nothrow @nogc @safe delegate() pure nothrow @safe Dg; |
| pragma(msg, Dg); |
| static assert(is(typeof(&foo) == Dg)); // should pass |
| } |
| |
| /***************************************************/ |
| // 7499 |
| |
| void test7499() |
| { |
| int function(int)[] a1 = [ x => x ]; // 7499 |
| int function(int)[][] a2 = [[x => x]]; // +a |
| assert(a1[0] (10) == 10); |
| assert(a2[0][0](10) == 10); |
| } |
| |
| /***************************************************/ |
| // 7500 |
| |
| void test7500() |
| { |
| alias immutable bool function(int[]) Foo; |
| Foo f = a => true; |
| } |
| |
| /***************************************************/ |
| // 7525 |
| |
| void test7525() |
| { |
| { |
| char[] delegate() a = { return null; }; |
| int delegate() b = { return 1U; }; |
| uint delegate() c = { return 1; }; |
| float delegate() d = { return 1.0; }; |
| double delegate() e = { return 1.0f; }; |
| } |
| |
| { |
| char[] delegate(int) a = (x){ return null; }; |
| int delegate(int) b = (x){ return 1U; }; |
| uint delegate(int) c = (x){ return 1; }; |
| float delegate(int) d = (x){ return 1.0; }; |
| double delegate(int) e = (x){ return 1.0f; }; |
| } |
| } |
| |
| /***************************************************/ |
| // 7582 |
| |
| void test7582() |
| { |
| void delegate(int) foo; |
| void delegate(int) foo2; |
| foo = (a) { |
| foo2 = (b) { }; |
| }; |
| } |
| |
| /***************************************************/ |
| // 7649 |
| |
| void test7649() |
| { |
| void foo(int function(int) fp = x => 1) |
| { |
| assert(fp(1) == 1); |
| } |
| foo(); |
| } |
| |
| /***************************************************/ |
| // 7650 |
| |
| void test7650() |
| { |
| int[int function(int)] aa1 = [x=>x:1, x=>x*2:2]; |
| foreach (k, v; aa1) { |
| if (v == 1) assert(k(10) == 10); |
| if (v == 2) assert(k(10) == 20); |
| } |
| |
| int function(int)[int] aa2 = [1:x=>x, 2:x=>x*2]; |
| assert(aa2[1](10) == 10); |
| assert(aa2[2](10) == 20); |
| |
| int n = 10; |
| int[int delegate(int)] aa3 = [x=>n+x:1, x=>n+x*2:2]; |
| foreach (k, v; aa3) { |
| if (v == 1) assert(k(10) == 20); |
| if (v == 2) assert(k(10) == 30); |
| } |
| |
| int delegate(int)[int] aa4 = [1:x=>n+x, 2:x=>n+x*2]; |
| assert(aa4[1](10) == 20); |
| assert(aa4[2](10) == 30); |
| } |
| |
| /***************************************************/ |
| // 7705 |
| |
| void test7705() |
| { |
| void foo1(void delegate(ref int ) dg){ int x=10; dg(x); } |
| foo1((ref x){ pragma(msg, typeof(x)); assert(x == 10); }); |
| static assert(!__traits(compiles, foo1((x){}) )); |
| |
| void foo2(void delegate(int, ...) dg){ dg(20, 3.14); } |
| foo2((x,...){ pragma(msg, typeof(x)); assert(x == 20); }); |
| |
| void foo3(void delegate(int[]...) dg){ dg(1, 2, 3); } |
| foo3((x ...){ pragma(msg, typeof(x)); assert(x == [1,2,3]); }); |
| } |
| |
| /***************************************************/ |
| // 7713 |
| |
| void foo7713(T)(T delegate(in Object) dlg) |
| {} |
| void test7713() |
| { |
| foo7713( (in obj) { return 15; } ); // line 6 |
| } |
| |
| /***************************************************/ |
| // 7743 |
| |
| auto foo7743a() |
| { |
| int x = 10; |
| return () nothrow { |
| return x; |
| }; |
| } |
| auto foo7743b() |
| { |
| int x = 10; |
| return () nothrow => x; |
| } |
| void test7743() |
| { |
| pragma(msg, typeof(&foo7743a)); |
| static assert(is(typeof(&foo7743a) == int delegate() pure nothrow @nogc @safe function() pure nothrow @safe)); |
| assert(foo7743a()() == 10); |
| |
| static assert(is(typeof(&foo7743b) == int delegate() pure nothrow @nogc @safe function() pure nothrow @safe)); |
| assert(foo7743b()() == 10); |
| } |
| |
| /***************************************************/ |
| // 7761 |
| |
| enum dg7761 = (int a) pure => 2 * a; |
| |
| void test7761() |
| { |
| static assert(is(typeof(dg7761) == int function(int) pure @safe nothrow @nogc)); |
| assert(dg7761(10) == 20); |
| } |
| |
| /***************************************************/ |
| // 7941 |
| |
| void test7941() |
| { |
| static assert(!__traits(compiles, { enum int c = function(){}; })); |
| } |
| |
| /***************************************************/ |
| // 8005 |
| |
| void test8005() |
| { |
| auto n = (a, int n = 2){ return n; }(1); |
| assert(n == 2); |
| } |
| |
| /***************************************************/ |
| // test8198 |
| |
| void test8198() |
| { |
| T delegate(T) zero(T)(T delegate(T) f) |
| { |
| return x => x; |
| } |
| |
| T delegate(T) delegate(T delegate(T)) succ(T)(T delegate(T) delegate(T delegate(T)) n) |
| { |
| return f => x => f(n(f)(x)); |
| } |
| |
| uint delegate(uint) delegate(uint delegate(uint)) n = &zero!uint; |
| foreach (i; 0..10) |
| { |
| assert(n(x => x + 1)(0) == i); |
| n = succ(n); |
| } |
| } |
| |
| /***************************************************/ |
| // 8226 |
| |
| immutable f8226 = (int x) => x * 2; |
| |
| void test8226() |
| { |
| assert(f8226(10) == 20); |
| } |
| |
| /***************************************************/ |
| // 8241 |
| |
| auto exec8241a(alias a = function(x) => x, T...)(T as) |
| { |
| return a(as); |
| } |
| |
| auto exec8241b(alias a = (x) => x, T...)(T as) |
| { |
| return a(as); |
| } |
| |
| void test8241() |
| { |
| exec8241a(2); |
| exec8241b(2); |
| } |
| |
| /***************************************************/ |
| // 8242 |
| |
| template exec8242(alias a, T...) |
| { |
| auto func8242(T as) |
| { |
| return a(as); |
| } |
| } |
| |
| mixin exec8242!(x => x, int); |
| mixin exec8242!((string x) => x, string); |
| |
| void test8242() |
| { |
| func8242(1); |
| func8242(""); |
| } |
| |
| /***************************************************/ |
| // 8315 |
| |
| void test8315() |
| { |
| bool b; |
| foo8315!(a => b)(); |
| } |
| |
| void foo8315(alias pred)() |
| if (is(typeof(pred(1)) == bool)) |
| {} |
| |
| /***************************************************/ |
| // 8397 |
| |
| void test8397() |
| { |
| void function(int) f; |
| static assert(!is(typeof({ |
| f = function(string x) {}; |
| }))); |
| } |
| |
| /***************************************************/ |
| // 8496 |
| |
| void test8496() |
| { |
| alias extern (C) void function() Func; |
| |
| Func fp = (){}; |
| |
| fp = (){}; |
| } |
| |
| /***************************************************/ |
| // 8575 |
| |
| template tfunc8575(func...) |
| { |
| auto tfunc8575(U)(U u) { return func[0](u); } |
| } |
| auto bar8575(T)(T t) |
| { |
| return tfunc8575!(a => a)(t); |
| } |
| void foo8575a() { assert(bar8575(uint.init + 1) == +1); } |
| void foo8575b() { assert(bar8575( int.init - 1) == -1); } |
| |
| void test8575() |
| { |
| foo8575a(); |
| foo8575b(); |
| } |
| |
| /***************************************************/ |
| // 9153 |
| |
| void writeln9153(string s){} |
| |
| void test9153() |
| { |
| auto tbl1 = [ |
| (string x) { writeln9153(x); }, |
| (string x) { x ~= 'a'; }, |
| ]; |
| auto tbl2 = [ |
| (string x) { x ~= 'a'; }, |
| (string x) { writeln9153(x); }, |
| ]; |
| } |
| |
| /***************************************************/ |
| // 9393 |
| |
| template ifThrown9393a(E) |
| { |
| void ifThrown9393a(T)(scope T delegate(E) errHandler) |
| { |
| } |
| } |
| void ifThrown9393b(E, T)(scope T delegate(E) errHandler) |
| { |
| } |
| |
| void foo9393(T)(void delegate(T) dg){ dg(T.init); } |
| void foo9393()(void delegate(int) dg){ foo9393!int(dg); } |
| |
| void test9393() |
| { |
| ifThrown9393a!Exception(e => 10); |
| ifThrown9393b!Exception(e => 10); |
| |
| foo9393((x){ assert(x == int.init); }); |
| } |
| |
| /***************************************************/ |
| // 9415 |
| |
| void test9415() |
| { |
| int z; |
| typeof((int a){return z;}) dg; |
| dg = (int a){return z;}; |
| } |
| |
| /***************************************************/ |
| // 9628 |
| |
| template TypeTuple9628(TL...) { alias TypeTuple9628 = TL; } |
| void map9628(alias func)() { func(0); } |
| |
| void test9628() |
| { |
| auto items = [[10, 20], [30]]; |
| size_t[] res; |
| |
| res = null; |
| foreach (_; 0 .. 2) |
| { |
| foreach (sub; items) |
| { |
| map9628!(( i){ res ~= sub.length; }); |
| map9628!((size_t i){ res ~= sub.length; }); |
| } |
| } |
| assert(res == [2,2,1,1, 2,2,1,1]); |
| |
| res = null; |
| foreach (_; TypeTuple9628!(0, 1)) |
| { |
| foreach (sub; items) |
| { |
| map9628!(( i){ res ~= sub.length; }); |
| map9628!((size_t i){ res ~= sub.length; }); |
| } |
| } |
| assert(res == [2,2,1,1, 2,2,1,1]); |
| } |
| |
| /***************************************************/ |
| // 9928 |
| |
| void test9928() |
| { |
| void* smth = (int x) { return x; }; |
| } |
| |
| /***************************************************/ |
| // 10133 |
| |
| ptrdiff_t countUntil10133(alias pred, R)(R haystack) |
| { |
| typeof(return) i; |
| |
| alias T = dchar; |
| |
| foreach (T elem; haystack) |
| { |
| if (pred(elem)) return i; |
| ++i; |
| } |
| |
| return -1; |
| } |
| |
| bool func10133(string s)() if (countUntil10133!(x => x == 'x')(s) == 1) |
| { |
| return true; |
| } |
| |
| bool func10133a(string s)() if (countUntil10133!(x => s == "x")(s) != -1) |
| { |
| return true; |
| } |
| bool func10133b(string s)() if (countUntil10133!(x => s == "x")(s) != -1) |
| { |
| return true; |
| } |
| |
| void test10133() |
| { |
| func10133!("ax")(); |
| |
| func10133a!("x")(); |
| static assert(!is(typeof(func10133a!("ax")()))); |
| static assert(!is(typeof(func10133b!("ax")()))); |
| func10133b!("x")(); |
| } |
| |
| /***************************************************/ |
| // 10219 |
| |
| void test10219() |
| { |
| interface I { } |
| class C : I { } |
| |
| void test_dg(I delegate(C) dg) |
| { |
| C c = new C; |
| void* cptr = cast(void*) c; |
| void* iptr = cast(void*) cast(I) c; |
| void* xptr = cast(void*) dg(c); |
| assert(cptr != iptr); |
| assert(cptr != xptr); // should pass |
| assert(iptr == xptr); // should pass |
| } |
| |
| C delegate(C c) dg = delegate C(C c) { return c; }; |
| static assert(!__traits(compiles, { test_dg(dg); })); |
| static assert(!__traits(compiles, { test_dg(delegate C(C c) { return c; }); })); |
| static assert(!__traits(compiles, { I delegate(C) dg2 = dg; })); |
| |
| // creates I delegate(C) |
| test_dg(c => c); |
| test_dg(delegate(C c) => c); |
| |
| void test_fp(I function(C) fp) |
| { |
| C c = new C; |
| void* cptr = cast(void*) c; |
| void* iptr = cast(void*) cast(I) c; |
| void* xptr = cast(void*) fp(c); |
| assert(cptr != iptr); |
| assert(cptr != xptr); // should pass |
| assert(iptr == xptr); // should pass |
| } |
| |
| C function(C c) fp = function C(C c) { return c; }; |
| static assert(!__traits(compiles, { test_fp(fp); })); |
| static assert(!__traits(compiles, { test_fp(function C(C c) { return c; }); })); |
| static assert(!__traits(compiles, { I function(C) fp2 = fp; })); |
| |
| // creates I function(C) |
| test_fp(c => c); |
| test_fp(function(C c) => c); |
| } |
| |
| /***************************************************/ |
| // 10288 |
| |
| T foo10288(T)(T x) |
| { |
| void lambda() @trusted nothrow { x += 10; } |
| lambda(); |
| return x; |
| } |
| |
| T bar10288(T)(T x) |
| { |
| () @trusted { x += 10; } (); |
| return x; |
| } |
| |
| T baz10288(T)(T arg) |
| { |
| static int g = 10; |
| () @trusted { x += g; } (); |
| return x; |
| } |
| |
| void test10288() @safe pure nothrow |
| { |
| assert(foo10288(10) == 20); // OK |
| assert(bar10288(10) == 20); // OK <- NG |
| static assert(!__traits(compiles, baz10288(10))); |
| } |
| |
| /***************************************************/ |
| // 10666 |
| |
| struct S10666 |
| { |
| int val; |
| ~this() {} |
| } |
| |
| void foo10666(S10666 s1) |
| { |
| S10666 s2; |
| |
| /* Even if closureVars(s1 and s2) are accessed by directly called lambdas, |
| * they won't escape the scope of this function. |
| */ |
| auto x1 = (){ return s1.val; }(); // OK |
| auto x2 = (){ return s2.val; }(); // OK |
| } |
| |
| /***************************************************/ |
| // 11081 |
| |
| T ifThrown11081(E : Throwable, T)(T delegate(E) errorHandler) |
| { |
| return errorHandler(); |
| } |
| |
| void test11081() |
| { |
| static if (__traits(compiles, ifThrown11081!Exception(e => 0))) |
| { |
| } |
| static if (__traits(compiles, ifThrown11081!Exception(e => 0))) |
| { |
| } |
| } |
| |
| /***************************************************/ |
| // 11220 |
| |
| int parsePrimaryExp11220(int x) |
| { |
| parseAmbig11220!( (parsed){ x += 1; } )(); |
| return 1; |
| } |
| |
| typeof(handler(1)) parseAmbig11220(alias handler)() |
| { |
| return handler(parsePrimaryExp11220(1)); |
| } |
| |
| /***************************************************/ |
| // 11230 |
| |
| template map11230(fun...) |
| { |
| auto map11230(Range)(Range r) |
| { |
| return MapResult11230!(fun, Range)(r); |
| } |
| } |
| |
| struct MapResult11230(alias fun, R) |
| { |
| R _input; |
| this(R input) { _input = input; } |
| } |
| |
| class A11230 { A11230[] as; } |
| class B11230 { A11230[] as; } |
| class C11230 : A11230 {} |
| |
| C11230 visit11230(A11230 a) |
| { |
| a.as.map11230!(a => visit11230); |
| return null; |
| } |
| C11230 visit11230(B11230 b) |
| { |
| b.as.map11230!(a => visit11230); |
| return null; |
| } |
| C11230 visit11230() |
| { |
| return null; |
| } |
| |
| /***************************************************/ |
| // 10336 |
| |
| struct S10336 |
| { |
| template opDispatch(string name) |
| { |
| enum opDispatch = function(int x) { |
| return x; |
| }; |
| } |
| } |
| |
| void test10336() |
| { |
| S10336 s; |
| assert(s.hello(12) == 12); |
| } |
| |
| /***************************************************/ |
| // 10928 |
| |
| struct D10928 |
| { |
| int x; |
| ~this() @nogc {} |
| } |
| |
| void f10928a(D10928 bar) |
| { |
| (){ bar.x++; }(); |
| } |
| void f10928b(D10928 bar) @nogc |
| { |
| (){ bar.x++; }(); |
| } |
| |
| void test10928() |
| { |
| f10928a(D10928.init); |
| f10928b(D10928.init); |
| } |
| |
| /***************************************************/ |
| // 11661 |
| |
| void test11661() |
| { |
| void delegate() dg = {}; // OK |
| void function() fp = {}; // OK <- NG |
| } |
| |
| /***************************************************/ |
| // 11774 |
| |
| void f11774(T, R)(R delegate(T[]) dg) |
| { |
| T[] src; |
| dg(src); |
| } |
| |
| void test11774() |
| { |
| int[] delegate(int[]) dg = (int[] a) => a; |
| f11774!int(dg); |
| f11774!Object(a => a); |
| f11774!int(dg); |
| } |
| |
| /***************************************************/ |
| // 12421 |
| |
| void test12421() |
| { |
| void test(string decl, bool polymorphic = true)() |
| { |
| // parse AliasDeclaration in Statement |
| mixin("alias f = " ~ decl ~ ";"); |
| assert(f(1) == 1); |
| static if (polymorphic) |
| assert(f("s") == "s"); |
| |
| // parse AliasDeclaration in DeclDefs |
| mixin("template X() { alias g = " ~ decl ~ "; }"); |
| alias g = X!().g; |
| assert(g(1) == 1); |
| static if (polymorphic) |
| assert(g("s") == "s"); |
| } |
| |
| test!(q{ x => x }); |
| test!(q{ ( x) => x }); |
| test!(q{ (int x) => x }, false); |
| |
| test!(q{ ( x){ return x; } }); |
| test!(q{ (int x){ return x; } }, false); |
| |
| test!(q{ function ( x) => x }); |
| test!(q{ function (int x) => x }, false); |
| test!(q{ function int ( x) => x }, false); |
| test!(q{ function int (int x) => x }, false); |
| |
| test!(q{ delegate ( x) => x }); |
| test!(q{ delegate (int x) => x }, false); |
| test!(q{ delegate int ( x) => x }, false); |
| test!(q{ delegate int (int x) => x }, false); |
| |
| test!(q{ function ( x){ return x; } }); |
| test!(q{ function (int x){ return x; } }, false); |
| test!(q{ function int ( x){ return x; } }, false); |
| test!(q{ function int (int x){ return x; } }, false); |
| |
| test!(q{ delegate ( x){ return x; } }); |
| test!(q{ delegate (int x){ return x; } }, false); |
| test!(q{ delegate int ( x){ return x; } }, false); |
| test!(q{ delegate int (int x){ return x; } }, false); |
| |
| // This is problematic case, and should be disallowed in the future. |
| alias f = x => y; |
| int y = 10; |
| assert(f(1) == 10); |
| } |
| |
| /***************************************************/ |
| // 12508 |
| |
| interface A12508(T) |
| { |
| T getT(); |
| } |
| |
| class C12508 : A12508!double |
| { |
| double getT() { return 1; } |
| } |
| |
| void f12508(A12508!double delegate() dg) |
| { |
| auto a = dg(); |
| assert(a !is null); |
| assert(a.getT() == 1.0); // fails! |
| } |
| |
| void t12508(T)(A12508!T delegate() dg) |
| { |
| auto a = dg(); |
| assert(a !is null); |
| assert(a.getT() == 1.0); // fails! |
| } |
| |
| ref alias Dg12508 = A12508!double delegate(); |
| void t12508(T)(Dg12508 dg) {} |
| |
| void test12508() |
| { |
| f12508({ return new C12508(); }); |
| t12508({ return new C12508(); }); |
| static assert(!__traits(compiles, x12508({ return new C12508(); }))); |
| } |
| |
| /***************************************************/ |
| // 13879 |
| |
| void test13879() |
| { |
| bool function(int)[2] funcs1 = (int x) => true; // OK |
| assert(funcs1[0] is funcs1[1]); |
| funcs1[0] = x => true; // OK |
| bool function(int)[2] funcs2 = x => true; // OK <- Error |
| assert(funcs2[0] is funcs2[1]); |
| } |
| |
| /***************************************************/ |
| // 14745 |
| |
| void test14745() |
| { |
| // qualified nested functions |
| auto foo1() pure immutable { return 0; } |
| auto foo2() pure const { return 0; } |
| |
| // qualified lambdas (== implicitly marked as delegate literals) |
| auto lambda1 = () pure immutable { return 0; }; |
| auto lambda2 = () pure const { return 0; }; |
| static assert(is(typeof(lambda1) : typeof(&foo1))); |
| static assert(is(typeof(lambda2) : typeof(&foo2))); |
| |
| // qualified delegate literals |
| auto dg1 = delegate () pure immutable { return 0; }; |
| auto dg2 = delegate () pure const { return 0; }; |
| static assert(is(typeof(dg1) : typeof(&foo1))); |
| static assert(is(typeof(dg2) : typeof(&foo2))); |
| } |
| |
| /***************************************************/ |
| // 15794 |
| |
| struct Foo15794 |
| { |
| static void fun(Holder)() |
| { |
| int i = Holder.fn(); |
| } |
| } |
| |
| struct Holder15794(alias Fn) |
| { |
| alias fn = Fn; |
| } |
| |
| void gun15794(alias fn, U...)() |
| { |
| Foo15794.fun!(Holder15794!fn)(); |
| } |
| |
| void test15794() |
| { |
| gun15794!(() => 0)(); // Line 26 |
| } |
| |
| /***************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=16271 |
| |
| ref auto funa16271(alias dg, T)(ref T a) |
| { |
| return dg(a); |
| } |
| |
| ref auto func16271(alias dg)() |
| { |
| return dg(); |
| } |
| |
| void assign16271(T)(ref T a, T b) |
| { |
| alias fun = ref (ref a) => a; |
| fun(a) = b; |
| } |
| |
| void test16271() |
| { |
| int x; |
| (ref () => x )() = 1; assert(x == 1); |
| func16271!(ref () => x) = 2; assert(x == 2); |
| assign16271(x, 3); assert(x == 3); |
| |
| alias alx = func16271!(ref () => x); |
| alx = 4; assert(x == 4); |
| |
| alias alf = ref (ref a) => a; |
| auto auf = ref (ref int a) => a; |
| alf(x) = 5; assert(x == 5); |
| auf(x) = 6; assert(x == 6); |
| |
| assert((funa16271!( ref (ref a) => a)(x) += 1) == 7 ); |
| assert((funa16271!(function ref (ref a) => a)(x) += 1) == 8 ); |
| assert((funa16271!(function ref int(ref a) => a)(x) += 1) == 9 ); |
| assert((funa16271!(delegate ref (ref a) => a)(x) += 1) == 10); |
| assert((funa16271!(delegate ref int(ref a) => a)(x) += 1) == 11); |
| assert(x == 11); |
| |
| alias aldc = ref () @trusted @nogc { return x; }; |
| auto audc = ref () @safe nothrow { return x; }; |
| alias alfuc = function ref (ref x) @trusted { return x; }; |
| alias aldec = delegate ref () @trusted { return x; }; |
| aldc() = 12; assert(x == 12); |
| audc() = 13; assert(x == 13); |
| alfuc(x) = 14; assert(x == 14); |
| aldec() = 15; assert(x == 15); |
| |
| template T() |
| { |
| int x; |
| alias alf = ref () => x; |
| auto auf = ref () => x; |
| } |
| T!().alf() = 1; assert(T!().x == 1); |
| T!().auf() = 2; assert(T!().x == 2); |
| } |
| |
| /***************************************************/ |
| |
| int main() |
| { |
| test1(); |
| test2(); |
| test3(); |
| test4(); |
| test4v(); |
| test5(); |
| test6(); |
| test7(); |
| test8(); |
| test9(); |
| test10(); |
| test11(); |
| test3235(); |
| test6714(); |
| test7193(); |
| test7202(); |
| test7288(); |
| test7499(); |
| test7500(); |
| test7525(); |
| test7582(); |
| test7649(); |
| test7650(); |
| test7705(); |
| test7713(); |
| test7743(); |
| test7761(); |
| test7941(); |
| test8005(); |
| test8198(); |
| test8226(); |
| test8241(); |
| test8242(); |
| test8315(); |
| test8397(); |
| test8496(); |
| test8575(); |
| test9153(); |
| test9393(); |
| test9415(); |
| test9628(); |
| test9928(); |
| test10133(); |
| test10219(); |
| test10288(); |
| test10336(); |
| test10928(); |
| test11661(); |
| test11774(); |
| test12421(); |
| test12508(); |
| test13879(); |
| test14745(); |
| test15794(); |
| test16271(); |
| |
| printf("Success\n"); |
| return 0; |
| } |