1367 lines
33 KiB
D
1367 lines
33 KiB
D
/*
|
|
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;
|
|
}
|