140 lines
2.7 KiB
D
140 lines
2.7 KiB
D
extern (C) int printf(const(char*) fmt, ...);
|
|
|
|
static int foo();
|
|
|
|
/**********************************/
|
|
|
|
auto red()()
|
|
{
|
|
return foo();
|
|
}
|
|
|
|
void test13350()
|
|
{
|
|
int[] data;
|
|
assert(is(typeof(red())));
|
|
}
|
|
|
|
/**********************************/
|
|
|
|
struct A1(T) { void f1() {} }
|
|
struct B1(T) { void f2() {} }
|
|
|
|
A1!(B1!int) func1()() { return typeof(return).init; }
|
|
|
|
void test1()
|
|
{
|
|
static if (is(typeof(func1()) R : X!(Y), alias X, Y))
|
|
{
|
|
R.init.f1();
|
|
Y.init.f2();
|
|
}
|
|
else
|
|
static assert(0);
|
|
}
|
|
|
|
/**********************************/
|
|
|
|
struct A2(T) { void f1() { foo(); } }
|
|
struct B2(T) { void f2() { foo(); } }
|
|
|
|
A2!(B2!int) func2()() { return typeof(return).init; }
|
|
|
|
void test2()
|
|
{
|
|
static if (is(typeof(func2())))
|
|
{
|
|
}
|
|
else
|
|
static assert(0);
|
|
}
|
|
|
|
/**********************************/
|
|
|
|
template A3() { void foo() { B3!().bar(); } }
|
|
template B3() { void bar() {} }
|
|
|
|
void test3()
|
|
{
|
|
// A3!() and B3!() are marked as 'speculative'
|
|
static assert(is(typeof(A3!().foo())));
|
|
|
|
// A3!() is unspeculative, but B3!() isn't.
|
|
A3!().foo();
|
|
|
|
// in codegen phase, B3!() will generate its members, because
|
|
// the tinst chain contains unspeculative instance A3!().
|
|
}
|
|
|
|
/**********************************/
|
|
|
|
struct S4(T)
|
|
{
|
|
string toString() const { return "instantiated"; }
|
|
}
|
|
|
|
void test4()
|
|
{
|
|
// inside typeof is not speculative context
|
|
alias X = typeof(S4!int());
|
|
assert(typeid(X).xtoString !is null);
|
|
}
|
|
|
|
/**********************************/
|
|
|
|
struct S5(T)
|
|
{
|
|
string toString() const { return "instantiated"; }
|
|
}
|
|
|
|
void test5()
|
|
{
|
|
enum x = S5!int();
|
|
assert(x.toString() == "instantiated");
|
|
}
|
|
|
|
/**********************************/
|
|
|
|
int foo6()() { return 0; }
|
|
|
|
template A6() { alias f = foo6!(); }
|
|
void testa6()() if (is(typeof(A6!().f))) {}
|
|
|
|
template B6() { alias f = foo6!(); }
|
|
void testb6()() if (is(typeof(B6!().f))) {}
|
|
|
|
template C6() { void f() { B6!().f(); } }
|
|
|
|
void test6()
|
|
{
|
|
testa6();
|
|
// foo6!() is speculatively instantiated from A6!() [TemplateInstance a]
|
|
// -> foo6!() is instantiated in A6!(), so it should be inserted to the members of this module.
|
|
|
|
testb6();
|
|
// foo6!() is speculatively instantiated from B6!() [TemplateInstance b],
|
|
// but the tinst of cached [TemplateInstance a] is not changed.
|
|
// -> insert [b] to the tnext chain of [a]
|
|
|
|
C6!().f();
|
|
// foo6!() is used through C6!(), so it should be linked to the final executable.
|
|
// but its first instance does not link to any non-speculative instances.
|
|
// -> look for tnext chain and determine its codegen is really necessary.
|
|
}
|
|
|
|
/**********************************/
|
|
|
|
int main()
|
|
{
|
|
test13350();
|
|
test1();
|
|
test2();
|
|
test3();
|
|
test4();
|
|
test5();
|
|
test6();
|
|
|
|
printf("Success\n");
|
|
return 0;
|
|
}
|