2061 lines
42 KiB
D
2061 lines
42 KiB
D
/*
|
|
TEST_OUTPUT:
|
|
---
|
|
false
|
|
[] = int
|
|
[] = string
|
|
[0] = int
|
|
[1] = string
|
|
[] = string
|
|
[] = int
|
|
[1] = string
|
|
[0] = int
|
|
---
|
|
|
|
RUN_OUTPUT:
|
|
---
|
|
1 1.1
|
|
ctor
|
|
cpctor
|
|
dtor
|
|
cpctor
|
|
dtor
|
|
dtor
|
|
Success
|
|
---
|
|
*/
|
|
|
|
extern (C) int printf(const(char*) fmt, ...);
|
|
import core.vararg;
|
|
|
|
struct Tup(T...)
|
|
{
|
|
T field;
|
|
alias field this;
|
|
|
|
bool opEquals(const Tup rhs) const
|
|
{
|
|
foreach (i, _; T)
|
|
if (field[i] != rhs.field[i])
|
|
return false;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
Tup!T tup(T...)(T fields)
|
|
{
|
|
return typeof(return)(fields);
|
|
}
|
|
|
|
template Seq(T...)
|
|
{
|
|
alias T Seq;
|
|
}
|
|
|
|
/**********************************************/
|
|
|
|
struct S
|
|
{
|
|
int x;
|
|
alias x this;
|
|
}
|
|
|
|
int foo(int i)
|
|
{
|
|
return i * 2;
|
|
}
|
|
|
|
void test1()
|
|
{
|
|
S s;
|
|
s.x = 7;
|
|
int i = -s;
|
|
assert(i == -7);
|
|
|
|
i = s + 8;
|
|
assert(i == 15);
|
|
|
|
i = s + s;
|
|
assert(i == 14);
|
|
|
|
i = 9 + s;
|
|
assert(i == 16);
|
|
|
|
i = foo(s);
|
|
assert(i == 14);
|
|
}
|
|
|
|
/**********************************************/
|
|
|
|
class C
|
|
{
|
|
int x;
|
|
alias x this;
|
|
}
|
|
|
|
void test2()
|
|
{
|
|
C s = new C();
|
|
s.x = 7;
|
|
int i = -s;
|
|
assert(i == -7);
|
|
|
|
i = s + 8;
|
|
assert(i == 15);
|
|
|
|
i = s + s;
|
|
assert(i == 14);
|
|
|
|
i = 9 + s;
|
|
assert(i == 16);
|
|
|
|
i = foo(s);
|
|
assert(i == 14);
|
|
}
|
|
|
|
/**********************************************/
|
|
|
|
void test3()
|
|
{
|
|
Tup!(int, double) t;
|
|
t[0] = 1;
|
|
t[1] = 1.1;
|
|
assert(t[0] == 1);
|
|
assert(t[1] == 1.1);
|
|
printf("%d %g\n", t[0], t[1]);
|
|
}
|
|
|
|
/**********************************************/
|
|
|
|
struct Iter
|
|
{
|
|
bool empty() { return true; }
|
|
void popFront() { }
|
|
ref Tup!(int, int) front() { return *new Tup!(int, int); }
|
|
ref Iter opSlice() { return this; }
|
|
}
|
|
|
|
void test4()
|
|
{
|
|
foreach (a; Iter()) { }
|
|
}
|
|
|
|
/**********************************************/
|
|
|
|
void test5()
|
|
{
|
|
static struct Double1 {
|
|
double val = 1;
|
|
alias val this;
|
|
}
|
|
static Double1 x() { return Double1(); }
|
|
x()++;
|
|
}
|
|
|
|
/**********************************************/
|
|
// 4617
|
|
|
|
struct S4617
|
|
{
|
|
struct F
|
|
{
|
|
int square(int n) { return n*n; }
|
|
real square(real n) { return n*n; }
|
|
}
|
|
F forward;
|
|
|
|
alias forward this;
|
|
|
|
alias forward.square sqr; // okay
|
|
|
|
int field;
|
|
void mfunc();
|
|
template Templ(){}
|
|
void tfunc()(){}
|
|
}
|
|
|
|
template Id4617(alias k) { alias k Id4617; }
|
|
|
|
void test4617a()
|
|
{
|
|
alias Id4617!(S4617.square) test1; //NG
|
|
alias Id4617!(S4617.forward.square) test2; //OK
|
|
|
|
alias Id4617!(S4617.sqr) test3; //okay
|
|
|
|
static assert(__traits(isSame, S4617.square, S4617.forward.square));
|
|
}
|
|
|
|
void test4617b()
|
|
{
|
|
static struct Sub(T)
|
|
{
|
|
T value;
|
|
@property ref inout(T) payload() inout { return value; }
|
|
alias payload this;
|
|
}
|
|
|
|
alias Id4617!(S4617.field) S_field;
|
|
alias Id4617!(S4617.mfunc) S_mfunc;
|
|
alias Id4617!(S4617.Templ) S_Templ;
|
|
alias Id4617!(S4617.tfunc) S_tfunc;
|
|
|
|
alias Sub!S4617 T4617;
|
|
alias Id4617!(T4617.field) R_field;
|
|
alias Id4617!(T4617.mfunc) R_mfunc;
|
|
alias Id4617!(T4617.Templ) R_Templ;
|
|
alias Id4617!(T4617.tfunc) R_tfunc;
|
|
static assert(__traits(isSame, R_field, S_field));
|
|
static assert(__traits(isSame, R_mfunc, S_mfunc));
|
|
static assert(__traits(isSame, R_Templ, S_Templ));
|
|
static assert(__traits(isSame, R_tfunc, S_tfunc));
|
|
|
|
alias Id4617!(T4617.square) R_sqr;
|
|
static assert(__traits(isSame, R_sqr, S4617.forward.square));
|
|
}
|
|
|
|
/**********************************************/
|
|
// 4773
|
|
|
|
void test4773()
|
|
{
|
|
struct Rebindable
|
|
{
|
|
Object obj;
|
|
@property const(Object) get(){ return obj; }
|
|
alias get this;
|
|
}
|
|
|
|
Rebindable r;
|
|
if (r) assert(0);
|
|
r.obj = new Object;
|
|
if (!r) assert(0);
|
|
}
|
|
|
|
/**********************************************/
|
|
// 5188
|
|
|
|
void test5188()
|
|
{
|
|
struct S
|
|
{
|
|
int v = 10;
|
|
alias v this;
|
|
}
|
|
|
|
S s;
|
|
assert(s <= 20);
|
|
assert(s != 14);
|
|
}
|
|
|
|
/***********************************************/
|
|
|
|
struct Foo {
|
|
void opIndexAssign(int x, size_t i) {
|
|
val = x;
|
|
}
|
|
void opSliceAssign(int x, size_t a, size_t b) {
|
|
val = x;
|
|
}
|
|
int val;
|
|
}
|
|
|
|
struct Bar {
|
|
Foo foo;
|
|
alias foo this;
|
|
}
|
|
|
|
void test6() {
|
|
Bar b;
|
|
b[0] = 1;
|
|
assert(b.val == 1);
|
|
b[0 .. 1] = 2;
|
|
assert(b.val == 2);
|
|
}
|
|
|
|
/**********************************************/
|
|
// recursive alias this detection
|
|
|
|
class C0 {}
|
|
|
|
class C1 { C2 c; alias c this; }
|
|
class C2 { C1 c; alias c this; }
|
|
|
|
class C3 { C2 c; alias c this; }
|
|
|
|
struct S0 {}
|
|
|
|
struct S1 { S2* ps; @property ref get(){return *ps;} alias get this; }
|
|
struct S2 { S1* ps; @property ref get(){return *ps;} alias get this; }
|
|
|
|
struct S3 { S2* ps; @property ref get(){return *ps;} alias get this; }
|
|
|
|
struct S4 { S5* ps; @property ref get(){return *ps;} alias get this; }
|
|
struct S5 { S4* ps; @property ref get(){return *ps;} alias get this; }
|
|
|
|
struct S6 { S5* ps; @property ref get(){return *ps;} alias get this; }
|
|
|
|
void test7()
|
|
{
|
|
// Able to check a type is implicitly convertible within a finite time.
|
|
static assert(!is(C1 : C0));
|
|
static assert( is(C2 : C1));
|
|
static assert( is(C1 : C2));
|
|
static assert(!is(C3 : C0));
|
|
static assert( is(C3 : C1));
|
|
static assert( is(C3 : C2));
|
|
|
|
static assert(!is(S1 : S0));
|
|
static assert( is(S2 : S1));
|
|
static assert( is(S1 : S2));
|
|
static assert(!is(S3 : S0));
|
|
static assert( is(S3 : S1));
|
|
static assert( is(S3 : S2));
|
|
|
|
C0 c0; C1 c1; C3 c3;
|
|
S0 s0; S1 s1; S3 s3; S4 s4; S6 s6;
|
|
|
|
// Allow merging types that contains alias this recursion.
|
|
static assert( __traits(compiles, c0 is c1)); // typeMerge(c || c) e2->implicitConvTo(t1);
|
|
static assert( __traits(compiles, c0 is c3)); // typeMerge(c || c) e2->implicitConvTo(t1);
|
|
static assert( __traits(compiles, c1 is c0)); // typeMerge(c || c) e1->implicitConvTo(t2);
|
|
static assert( __traits(compiles, c3 is c0)); // typeMerge(c || c) e1->implicitConvTo(t2);
|
|
static assert(!__traits(compiles, s1 is c0)); // typeMerge(c || c) e1
|
|
static assert(!__traits(compiles, s3 is c0)); // typeMerge(c || c) e1
|
|
static assert(!__traits(compiles, c0 is s1)); // typeMerge(c || c) e2
|
|
static assert(!__traits(compiles, c0 is s3)); // typeMerge(c || c) e2
|
|
|
|
static assert(!__traits(compiles, s1 is s0)); // typeMerge(s && s) e1
|
|
static assert(!__traits(compiles, s3 is s0)); // typeMerge(s && s) e1
|
|
static assert(!__traits(compiles, s0 is s1)); // typeMerge(s && s) e2
|
|
static assert(!__traits(compiles, s0 is s3)); // typeMerge(s && s) e2
|
|
static assert(!__traits(compiles, s1 is s4)); // typeMerge(s && s) e1 + e2
|
|
static assert(!__traits(compiles, s3 is s6)); // typeMerge(s && s) e1 + e2
|
|
|
|
static assert(!__traits(compiles, s1 is 10)); // typeMerge(s || s) e1
|
|
static assert(!__traits(compiles, s3 is 10)); // typeMerge(s || s) e1
|
|
static assert(!__traits(compiles, 10 is s1)); // typeMerge(s || s) e2
|
|
static assert(!__traits(compiles, 10 is s3)); // typeMerge(s || s) e2
|
|
|
|
// SliceExp::semantic
|
|
static assert(!__traits(compiles, c1[]));
|
|
static assert(!__traits(compiles, c3[]));
|
|
static assert(!__traits(compiles, s1[]));
|
|
static assert(!__traits(compiles, s3[]));
|
|
|
|
// CallExp::semantic
|
|
// static assert(!__traits(compiles, c1()));
|
|
// static assert(!__traits(compiles, c3()));
|
|
static assert(!__traits(compiles, s1()));
|
|
static assert(!__traits(compiles, s3()));
|
|
|
|
// AssignExp::semantic
|
|
static assert(!__traits(compiles, { c1[1] = 0; }));
|
|
static assert(!__traits(compiles, { c3[1] = 0; }));
|
|
static assert(!__traits(compiles, { s1[1] = 0; }));
|
|
static assert(!__traits(compiles, { s3[1] = 0; }));
|
|
static assert(!__traits(compiles, { c1[ ] = 0; }));
|
|
static assert(!__traits(compiles, { c3[ ] = 0; }));
|
|
static assert(!__traits(compiles, { s1[ ] = 0; }));
|
|
static assert(!__traits(compiles, { s3[ ] = 0; }));
|
|
|
|
// UnaExp::op_overload
|
|
static assert(!__traits(compiles, +c1[1]));
|
|
static assert(!__traits(compiles, +c3[1]));
|
|
static assert(!__traits(compiles, +s1[1]));
|
|
static assert(!__traits(compiles, +s3[1]));
|
|
static assert(!__traits(compiles, +c1[ ]));
|
|
static assert(!__traits(compiles, +c3[ ]));
|
|
static assert(!__traits(compiles, +s1[ ]));
|
|
static assert(!__traits(compiles, +s3[ ]));
|
|
static assert(!__traits(compiles, +c1));
|
|
static assert(!__traits(compiles, +c3));
|
|
static assert(!__traits(compiles, +s1));
|
|
static assert(!__traits(compiles, +s3));
|
|
|
|
// ArrayExp::op_overload
|
|
static assert(!__traits(compiles, c1[1]));
|
|
static assert(!__traits(compiles, c3[1]));
|
|
static assert(!__traits(compiles, s1[1]));
|
|
static assert(!__traits(compiles, s3[1]));
|
|
|
|
// BinExp::op_overload
|
|
static assert(!__traits(compiles, c1 + 10)); // e1
|
|
static assert(!__traits(compiles, c3 + 10)); // e1
|
|
static assert(!__traits(compiles, 10 + c1)); // e2
|
|
static assert(!__traits(compiles, 10 + c3)); // e2
|
|
static assert(!__traits(compiles, s1 + 10)); // e1
|
|
static assert(!__traits(compiles, s3 + 10)); // e1
|
|
static assert(!__traits(compiles, 10 + s1)); // e2
|
|
static assert(!__traits(compiles, 10 + s3)); // e2
|
|
|
|
// BinExp::compare_overload
|
|
static assert(!__traits(compiles, c1 < 10)); // (Object.opCmp(int) is invalid)
|
|
static assert(!__traits(compiles, c3 < 10)); // (Object.opCmp(int) is invalid)
|
|
static assert(!__traits(compiles, 10 < c1)); // (Object.opCmp(int) is invalid)
|
|
static assert(!__traits(compiles, 10 < c3)); // (Object.opCmp(int) is invalid)
|
|
static assert(!__traits(compiles, s1 < 10)); // e1
|
|
static assert(!__traits(compiles, s3 < 10)); // e1
|
|
static assert(!__traits(compiles, 10 < s1)); // e2
|
|
static assert(!__traits(compiles, 10 < s3)); // e2
|
|
|
|
// BinAssignExp::op_overload
|
|
static assert(!__traits(compiles, c1[1] += 1));
|
|
static assert(!__traits(compiles, c3[1] += 1));
|
|
static assert(!__traits(compiles, s1[1] += 1));
|
|
static assert(!__traits(compiles, s3[1] += 1));
|
|
static assert(!__traits(compiles, c1[ ] += 1));
|
|
static assert(!__traits(compiles, c3[ ] += 1));
|
|
static assert(!__traits(compiles, s1[ ] += 1));
|
|
static assert(!__traits(compiles, s3[ ] += 1));
|
|
static assert(!__traits(compiles, c1 += c0)); // e1
|
|
static assert(!__traits(compiles, c3 += c0)); // e1
|
|
static assert(!__traits(compiles, s1 += s0)); // e1
|
|
static assert(!__traits(compiles, s3 += s0)); // e1
|
|
static assert(!__traits(compiles, c0 += c1)); // e2
|
|
static assert(!__traits(compiles, c0 += c3)); // e2
|
|
static assert(!__traits(compiles, s0 += s1)); // e2
|
|
static assert(!__traits(compiles, s0 += s3)); // e2
|
|
static assert(!__traits(compiles, c1 += s1)); // e1 + e2
|
|
static assert(!__traits(compiles, c3 += s3)); // e1 + e2
|
|
|
|
// ForeachStatement::inferAggregate
|
|
static assert(!__traits(compiles, { foreach (e; s1){} }));
|
|
static assert(!__traits(compiles, { foreach (e; s3){} }));
|
|
static assert(!__traits(compiles, { foreach (e; c1){} }));
|
|
static assert(!__traits(compiles, { foreach (e; c3){} }));
|
|
|
|
// Expression::checkToBoolean
|
|
static assert(!__traits(compiles, { if (s1){} }));
|
|
static assert(!__traits(compiles, { if (s3){} }));
|
|
|
|
// SwitchStatement::semantic
|
|
static assert(!__traits(compiles, { switch (c0) { default: } }));
|
|
static assert(!__traits(compiles, { switch (c1) { default: } }));
|
|
static assert(!__traits(compiles, { switch (c3) { default: } }));
|
|
|
|
// Bugzilla 12537: function arguments with IFTI
|
|
void eq12537()(Object lhs) {}
|
|
const C0 cc0;
|
|
const C1 cc1;
|
|
const C3 cc3;
|
|
static assert(!__traits(compiles, eq12537(cc0)));
|
|
static assert(!__traits(compiles, eq12537(cc1)));
|
|
static assert(!__traits(compiles, eq12537(cc3)));
|
|
}
|
|
|
|
/***************************************************/
|
|
// 11875 - endless recursion in Type::deduceType
|
|
|
|
struct T11875x(C)
|
|
{
|
|
C c;
|
|
}
|
|
class D11875a { D11875b c; alias c this; }
|
|
class D11875b { D11875a c; alias c this; }
|
|
static assert(!is(D11875a == D11875b));
|
|
static assert( is(T11875x!D11875a == T11875x!D, D) && is(D == D11875a));
|
|
static assert(!is(D11875a == T11875x!D, D)); // this used to freeze dmd
|
|
|
|
// test that types in recursion are still detected
|
|
struct T11875y(C)
|
|
{
|
|
C c;
|
|
alias c this;
|
|
}
|
|
class D11875c { T11875y!D11875b c; alias c this; }
|
|
static assert(is(D11875c : T11875y!D, D) && is(D == D11875b));
|
|
|
|
/***************************************************/
|
|
// 11930
|
|
|
|
class BarObj11930 {}
|
|
|
|
struct Bar11930
|
|
{
|
|
BarObj11930 _obj;
|
|
alias _obj this;
|
|
}
|
|
|
|
BarObj11930 getBarObj11930(T)(T t)
|
|
{
|
|
static if (is(T unused : BarObj11930))
|
|
return t;
|
|
else
|
|
static assert(false, "Can not get BarObj from " ~ T.stringof);
|
|
}
|
|
|
|
void test11930()
|
|
{
|
|
Bar11930 b;
|
|
getBarObj11930(b);
|
|
}
|
|
|
|
/***************************************************/
|
|
// 2781
|
|
|
|
struct Tuple2781a(T...) {
|
|
T data;
|
|
alias data this;
|
|
}
|
|
|
|
struct Tuple2781b(T) {
|
|
T data;
|
|
alias data this;
|
|
}
|
|
|
|
void test2781()
|
|
{
|
|
Tuple2781a!(uint, float) foo;
|
|
foreach(elem; foo) {}
|
|
|
|
{
|
|
Tuple2781b!(int[]) bar1;
|
|
foreach(elem; bar1) {}
|
|
|
|
Tuple2781b!(int[int]) bar2;
|
|
foreach(key, elem; bar2) {}
|
|
|
|
Tuple2781b!(string) bar3;
|
|
foreach(dchar elem; bar3) {}
|
|
}
|
|
|
|
{
|
|
Tuple2781b!(int[]) bar1;
|
|
foreach(elem; bar1) goto L1;
|
|
L1:
|
|
;
|
|
|
|
Tuple2781b!(int[int]) bar2;
|
|
foreach(key, elem; bar2) goto L2;
|
|
L2:
|
|
;
|
|
|
|
Tuple2781b!(string) bar3;
|
|
foreach(dchar elem; bar3) goto L3;
|
|
L3:
|
|
;
|
|
}
|
|
|
|
|
|
int eval;
|
|
|
|
auto t1 = tup(10, "str");
|
|
auto i1 = 0;
|
|
foreach (e; t1)
|
|
{
|
|
pragma(msg, "[] = ", typeof(e));
|
|
static if (is(typeof(e) == int )) assert(i1 == 0 && e == 10);
|
|
static if (is(typeof(e) == string)) assert(i1 == 1 && e == "str");
|
|
++i1;
|
|
}
|
|
|
|
auto t2 = tup(10, "str");
|
|
foreach (i2, e; t2)
|
|
{
|
|
pragma(msg, "[", cast(int)i2, "] = ", typeof(e));
|
|
static if (is(typeof(e) == int )) { static assert(i2 == 0); assert(e == 10); }
|
|
static if (is(typeof(e) == string)) { static assert(i2 == 1); assert(e == "str"); }
|
|
}
|
|
|
|
auto t3 = tup(10, "str");
|
|
auto i3 = 2;
|
|
foreach_reverse (e; t3)
|
|
{
|
|
--i3;
|
|
pragma(msg, "[] = ", typeof(e));
|
|
static if (is(typeof(e) == int )) assert(i3 == 0 && e == 10);
|
|
static if (is(typeof(e) == string)) assert(i3 == 1 && e == "str");
|
|
}
|
|
|
|
auto t4 = tup(10, "str");
|
|
foreach_reverse (i4, e; t4)
|
|
{
|
|
pragma(msg, "[", cast(int)i4, "] = ", typeof(e));
|
|
static if (is(typeof(e) == int )) { static assert(i4 == 0); assert(e == 10); }
|
|
static if (is(typeof(e) == string)) { static assert(i4 == 1); assert(e == "str"); }
|
|
}
|
|
|
|
eval = 0;
|
|
foreach (i, e; tup(tup((){eval++; return 10;}(), 3.14), tup("str", [1,2])))
|
|
{
|
|
static if (i == 0) assert(e == tup(10, 3.14));
|
|
static if (i == 1) assert(e == tup("str", [1,2]));
|
|
}
|
|
assert(eval == 1);
|
|
|
|
eval = 0;
|
|
foreach (i, e; tup((){eval++; return 10;}(), tup(3.14, tup("str", tup([1,2])))))
|
|
{
|
|
static if (i == 0) assert(e == 10);
|
|
static if (i == 1) assert(e == tup(3.14, tup("str", tup([1,2]))));
|
|
}
|
|
assert(eval == 1);
|
|
}
|
|
|
|
/**********************************************/
|
|
// 6546
|
|
|
|
void test6546()
|
|
{
|
|
class C {}
|
|
class D : C {}
|
|
|
|
struct S { C c; alias c this; } // S : C
|
|
struct T { S s; alias s this; } // T : S
|
|
struct U { T t; alias t this; } // U : T
|
|
|
|
C c;
|
|
D d;
|
|
S s;
|
|
T t;
|
|
U u;
|
|
|
|
assert(c is c); // OK
|
|
assert(c is d); // OK
|
|
assert(c is s); // OK
|
|
assert(c is t); // OK
|
|
assert(c is u); // OK
|
|
|
|
assert(d is c); // OK
|
|
assert(d is d); // OK
|
|
assert(d is s); // doesn't work
|
|
assert(d is t); // doesn't work
|
|
assert(d is u); // doesn't work
|
|
|
|
assert(s is c); // OK
|
|
assert(s is d); // doesn't work
|
|
assert(s is s); // OK
|
|
assert(s is t); // doesn't work
|
|
assert(s is u); // doesn't work
|
|
|
|
assert(t is c); // OK
|
|
assert(t is d); // doesn't work
|
|
assert(t is s); // doesn't work
|
|
assert(t is t); // OK
|
|
assert(t is u); // doesn't work
|
|
|
|
assert(u is c); // OK
|
|
assert(u is d); // doesn't work
|
|
assert(u is s); // doesn't work
|
|
assert(u is t); // doesn't work
|
|
assert(u is u); // OK
|
|
}
|
|
|
|
/**********************************************/
|
|
// 6736
|
|
|
|
void test6736()
|
|
{
|
|
static struct S1
|
|
{
|
|
struct S2 // must be 8 bytes in size
|
|
{
|
|
uint a, b;
|
|
}
|
|
S2 s2;
|
|
alias s2 this;
|
|
}
|
|
S1 c;
|
|
static assert(!is(typeof(c + c)));
|
|
}
|
|
|
|
/**********************************************/
|
|
// 2777
|
|
|
|
struct ArrayWrapper(T) {
|
|
T[] array;
|
|
alias array this;
|
|
}
|
|
|
|
// alias array this
|
|
void test2777a()
|
|
{
|
|
ArrayWrapper!(uint) foo;
|
|
foo.length = 5; // Works
|
|
foo[0] = 1; // Works
|
|
auto e0 = foo[0]; // Works
|
|
auto e4 = foo[$ - 1]; // Error: undefined identifier __dollar
|
|
auto s01 = foo[0..2]; // Error: ArrayWrapper!(uint) cannot be sliced with[]
|
|
}
|
|
|
|
// alias tuple this
|
|
void test2777b()
|
|
{
|
|
auto t = tup(10, 3.14, "str", [1,2]);
|
|
|
|
assert(t[$ - 1] == [1,2]);
|
|
|
|
auto f1 = t[];
|
|
assert(f1[0] == 10);
|
|
assert(f1[1] == 3.14);
|
|
assert(f1[2] == "str");
|
|
assert(f1[3] == [1,2]);
|
|
|
|
auto f2 = t[1..3];
|
|
assert(f2[0] == 3.14);
|
|
assert(f2[1] == "str");
|
|
}
|
|
|
|
/****************************************/
|
|
// 2787
|
|
|
|
struct Base2787
|
|
{
|
|
int x;
|
|
void foo() { auto _ = x; }
|
|
}
|
|
|
|
struct Derived2787
|
|
{
|
|
Base2787 _base;
|
|
alias _base this;
|
|
int y;
|
|
void bar() { auto _ = x; }
|
|
}
|
|
|
|
/***********************************/
|
|
// 5679
|
|
|
|
void test5679()
|
|
{
|
|
class Foo {}
|
|
|
|
class Base
|
|
{
|
|
@property Foo getFoo() { return null; }
|
|
}
|
|
class Derived : Base
|
|
{
|
|
alias getFoo this;
|
|
}
|
|
|
|
Derived[] dl;
|
|
Derived d = new Derived();
|
|
dl ~= d; // Error: cannot append type alias_test.Base to type Derived[]
|
|
}
|
|
|
|
/***********************************/
|
|
// 6508
|
|
|
|
void test6508()
|
|
{
|
|
int x, y;
|
|
Seq!(x, y) = tup(10, 20);
|
|
assert(x == 10);
|
|
assert(y == 20);
|
|
}
|
|
|
|
void test6508x()
|
|
{
|
|
static int ctor, cpctor, dtor;
|
|
|
|
static struct Tuple(T...)
|
|
{
|
|
T field;
|
|
alias field this;
|
|
|
|
this(int) { ++ctor; printf("ctor\n"); }
|
|
this(this) { ++cpctor; printf("cpctor\n"); }
|
|
~this() { ++dtor; printf("dtor\n"); }
|
|
}
|
|
|
|
{
|
|
alias Tup = Tuple!(int, string);
|
|
auto tup = Tup(1);
|
|
assert(ctor==1 && cpctor==0 && dtor==0);
|
|
|
|
auto getVal() { return tup; }
|
|
ref getRef(ref Tup s = tup) { return s; }
|
|
|
|
{
|
|
auto n1 = tup[0];
|
|
assert(ctor==1 && cpctor==0 && dtor==0);
|
|
|
|
auto n2 = getRef()[0];
|
|
assert(ctor==1 && cpctor==0 && dtor==0);
|
|
|
|
auto n3 = getVal()[0];
|
|
assert(ctor==1 && cpctor==1 && dtor==1);
|
|
}
|
|
|
|
// bug in DotVarExp::semantic
|
|
{
|
|
typeof(tup.field) vars;
|
|
vars = getVal();
|
|
assert(ctor==1 && cpctor==2 && dtor==2);
|
|
}
|
|
}
|
|
assert(ctor==1 && cpctor==2 && dtor==3);
|
|
assert(ctor + cpctor == dtor);
|
|
}
|
|
|
|
/***********************************/
|
|
// 6369
|
|
|
|
void test6369a()
|
|
{
|
|
alias Seq!(int, string) Field;
|
|
|
|
auto t1 = Tup!(int, string)(10, "str");
|
|
Field field1 = t1; // NG -> OK
|
|
assert(field1[0] == 10);
|
|
assert(field1[1] == "str");
|
|
|
|
auto t2 = Tup!(int, string)(10, "str");
|
|
Field field2 = t2.field; // NG -> OK
|
|
assert(field2[0] == 10);
|
|
assert(field2[1] == "str");
|
|
|
|
auto t3 = Tup!(int, string)(10, "str");
|
|
Field field3;
|
|
field3 = t3.field;
|
|
assert(field3[0] == 10);
|
|
assert(field3[1] == "str");
|
|
}
|
|
|
|
void test6369b()
|
|
{
|
|
auto t = Tup!(Tup!(int, double), string)(tup(10, 3.14), "str");
|
|
|
|
Seq!(int, double, string) fs1 = t;
|
|
assert(fs1[0] == 10);
|
|
assert(fs1[1] == 3.14);
|
|
assert(fs1[2] == "str");
|
|
|
|
Seq!(Tup!(int, double), string) fs2 = t;
|
|
assert(fs2[0][0] == 10);
|
|
assert(fs2[0][1] == 3.14);
|
|
assert(fs2[0] == tup(10, 3.14));
|
|
assert(fs2[1] == "str");
|
|
|
|
Tup!(Tup!(int, double), string) fs3 = t;
|
|
assert(fs3[0][0] == 10);
|
|
assert(fs3[0][1] == 3.14);
|
|
assert(fs3[0] == tup(10, 3.14));
|
|
assert(fs3[1] == "str");
|
|
}
|
|
|
|
void test6369c()
|
|
{
|
|
auto t = Tup!(Tup!(int, double), Tup!(string, int[]))(tup(10, 3.14), tup("str", [1,2]));
|
|
|
|
Seq!(int, double, string, int[]) fs1 = t;
|
|
assert(fs1[0] == 10);
|
|
assert(fs1[1] == 3.14);
|
|
assert(fs1[2] == "str");
|
|
assert(fs1[3] == [1,2]);
|
|
|
|
Seq!(int, double, Tup!(string, int[])) fs2 = t;
|
|
assert(fs2[0] == 10);
|
|
assert(fs2[1] == 3.14);
|
|
assert(fs2[2] == tup("str", [1,2]));
|
|
|
|
Seq!(Tup!(int, double), string, int[]) fs3 = t;
|
|
assert(fs3[0] == tup(10, 3.14));
|
|
assert(fs3[0][0] == 10);
|
|
assert(fs3[0][1] == 3.14);
|
|
assert(fs3[1] == "str");
|
|
assert(fs3[2] == [1,2]);
|
|
}
|
|
|
|
void test6369d()
|
|
{
|
|
int eval = 0;
|
|
Seq!(int, string) t = tup((){++eval; return 10;}(), "str");
|
|
assert(eval == 1);
|
|
assert(t[0] == 10);
|
|
assert(t[1] == "str");
|
|
}
|
|
|
|
/**********************************************/
|
|
// 6434
|
|
|
|
struct Variant6434{}
|
|
|
|
struct A6434
|
|
{
|
|
Variant6434 i;
|
|
alias i this;
|
|
|
|
void opDispatch(string name)()
|
|
{
|
|
}
|
|
}
|
|
|
|
void test6434()
|
|
{
|
|
A6434 a;
|
|
a.weird; // no property 'weird' for type 'VariantN!(maxSize)'
|
|
}
|
|
|
|
/**************************************/
|
|
// 6366
|
|
|
|
void test6366()
|
|
{
|
|
struct Zip
|
|
{
|
|
string str;
|
|
size_t i;
|
|
this(string s)
|
|
{
|
|
str = s;
|
|
}
|
|
@property const bool empty()
|
|
{
|
|
return i == str.length;
|
|
}
|
|
@property Tup!(size_t, char) front()
|
|
{
|
|
return typeof(return)(i, str[i]);
|
|
}
|
|
void popFront()
|
|
{
|
|
++i;
|
|
}
|
|
}
|
|
|
|
foreach (i, c; Zip("hello"))
|
|
{
|
|
switch (i)
|
|
{
|
|
case 0: assert(c == 'h'); break;
|
|
case 1: assert(c == 'e'); break;
|
|
case 2: assert(c == 'l'); break;
|
|
case 3: assert(c == 'l'); break;
|
|
case 4: assert(c == 'o'); break;
|
|
default:assert(0);
|
|
}
|
|
}
|
|
|
|
auto range(F...)(F field)
|
|
{
|
|
static struct Range {
|
|
F field;
|
|
bool empty = false;
|
|
Tup!F front() { return typeof(return)(field); }
|
|
void popFront(){ empty = true; }
|
|
}
|
|
return Range(field);
|
|
}
|
|
|
|
foreach (i, t; range(10, tup("str", [1,2]))){
|
|
static assert(is(typeof(i) == int));
|
|
static assert(is(typeof(t) == Tup!(string, int[])));
|
|
assert(i == 10);
|
|
assert(t == tup("str", [1,2]));
|
|
}
|
|
auto r1 = range(10, "str", [1,2]);
|
|
auto r2 = range(tup(10, "str"), [1,2]);
|
|
auto r3 = range(10, tup("str", [1,2]));
|
|
auto r4 = range(tup(10, "str", [1,2]));
|
|
alias Seq!(r1, r2, r3, r4) ranges;
|
|
foreach (n, _; ranges)
|
|
{
|
|
foreach (i, s, a; ranges[n]){
|
|
static assert(is(typeof(i) == int));
|
|
static assert(is(typeof(s) == string));
|
|
static assert(is(typeof(a) == int[]));
|
|
assert(i == 10);
|
|
assert(s == "str");
|
|
assert(a == [1,2]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/***************************************************/
|
|
// 6711
|
|
|
|
void test6711()
|
|
{
|
|
struct A { int i; }
|
|
struct B { A a; alias a this; }
|
|
struct C { B b; alias b this; }
|
|
|
|
B b;
|
|
with (b)
|
|
{
|
|
i = 42;
|
|
}
|
|
assert(b.i == 42);
|
|
|
|
C c;
|
|
with (c)
|
|
{
|
|
i = 42;
|
|
}
|
|
assert(c.i == 42);
|
|
}
|
|
|
|
/**********************************************/
|
|
// 12161
|
|
|
|
class A12161
|
|
{
|
|
void m() {}
|
|
}
|
|
|
|
class B12161
|
|
{
|
|
A12161 a;
|
|
alias a this;
|
|
}
|
|
|
|
void test12161()
|
|
{
|
|
B12161 b = new B12161();
|
|
b.a = new A12161();
|
|
with (b)
|
|
m();
|
|
}
|
|
|
|
/**********************************************/
|
|
// 6759
|
|
|
|
struct Range
|
|
{
|
|
size_t front() { return 0; }
|
|
void popFront() { empty = true; }
|
|
bool empty;
|
|
}
|
|
|
|
struct ARange
|
|
{
|
|
Range range;
|
|
alias range this;
|
|
}
|
|
|
|
void test6759()
|
|
{
|
|
ARange arange;
|
|
assert(arange.front == 0);
|
|
foreach(e; arange)
|
|
{
|
|
assert(e == 0);
|
|
}
|
|
}
|
|
|
|
/**********************************************/
|
|
// 6479
|
|
|
|
struct Memory6479
|
|
{
|
|
mixin Wrapper6479!();
|
|
}
|
|
struct Image6479
|
|
{
|
|
Memory6479 sup;
|
|
alias sup this;
|
|
}
|
|
mixin template Wrapper6479()
|
|
{
|
|
}
|
|
|
|
/**********************************************/
|
|
// 6832
|
|
|
|
void test6832()
|
|
{
|
|
static class Foo { }
|
|
static struct Bar { Foo foo; alias foo this; }
|
|
Bar bar;
|
|
bar = new Foo; // ok
|
|
assert(bar !is null); // ng
|
|
|
|
struct Int { int n; alias n this; }
|
|
Int a;
|
|
int b;
|
|
auto c = (true ? a : b); // TODO
|
|
assert(c == a);
|
|
}
|
|
|
|
/**********************************************/
|
|
// 6928
|
|
|
|
void test6928()
|
|
{
|
|
struct T { int* p; } // p is necessary.
|
|
T tx;
|
|
|
|
struct S {
|
|
T get() const { return tx; }
|
|
alias get this;
|
|
}
|
|
|
|
immutable(S) s;
|
|
immutable(T) t;
|
|
static assert(is(typeof(1? s:t))); // ok.
|
|
static assert(is(typeof(1? t:s))); // ok.
|
|
static assert(is(typeof(1? s:t)==typeof(1? t:s))); // fail.
|
|
|
|
auto x = 1? t:s; // ok.
|
|
auto y = 1? s:t; // compile error.
|
|
}
|
|
|
|
/**********************************************/
|
|
// 6929
|
|
|
|
struct S6929
|
|
{
|
|
T6929 get() const { return T6929.init; }
|
|
alias get this;
|
|
}
|
|
struct T6929
|
|
{
|
|
S6929 get() const { return S6929.init; }
|
|
alias get this;
|
|
}
|
|
void test6929()
|
|
{
|
|
T6929 t;
|
|
S6929 s;
|
|
static assert(!is(typeof(1? t:s)));
|
|
}
|
|
|
|
/***************************************************/
|
|
// 7136
|
|
|
|
void test7136()
|
|
{
|
|
struct X
|
|
{
|
|
Object get() immutable { return null; }
|
|
alias get this;
|
|
}
|
|
immutable(X) x;
|
|
Object y;
|
|
static assert( is(typeof(1?x:y) == Object)); // fails
|
|
static assert(!is(typeof(1?x:y) == const(Object))); // fails
|
|
|
|
struct A
|
|
{
|
|
int[] get() immutable { return null; }
|
|
alias get this;
|
|
}
|
|
immutable(A) a;
|
|
int[] b;
|
|
static assert( is(typeof(1?a:b) == int[])); // fails
|
|
static assert(!is(typeof(1?a:b) == const(int[]))); // fails
|
|
}
|
|
|
|
/***************************************************/
|
|
// 7731
|
|
|
|
struct A7731
|
|
{
|
|
int a;
|
|
}
|
|
template Inherit7731(alias X)
|
|
{
|
|
X __super;
|
|
alias __super this;
|
|
}
|
|
struct B7731
|
|
{
|
|
mixin Inherit7731!A7731;
|
|
int b;
|
|
}
|
|
|
|
struct PolyPtr7731(X)
|
|
{
|
|
X* _payload;
|
|
static if (is(typeof(X.init.__super)))
|
|
{
|
|
alias typeof(X.init.__super) Super;
|
|
@property auto getSuper(){ return PolyPtr7731!Super(&_payload.__super); }
|
|
alias getSuper this;
|
|
}
|
|
}
|
|
template create7731(X)
|
|
{
|
|
PolyPtr7731!X create7731(T...)(T args){
|
|
return PolyPtr7731!X(args);
|
|
}
|
|
}
|
|
|
|
void f7731a(PolyPtr7731!A7731 a) {/*...*/}
|
|
void f7731b(PolyPtr7731!B7731 b) {f7731a(b);/*...*/}
|
|
|
|
void test7731()
|
|
{
|
|
auto b = create7731!B7731();
|
|
}
|
|
|
|
/***************************************************/
|
|
// 7808
|
|
|
|
struct Nullable7808(T)
|
|
{
|
|
private T _value;
|
|
|
|
this()(T value)
|
|
{
|
|
_value = value;
|
|
}
|
|
|
|
@property ref inout(T) get() inout pure @safe
|
|
{
|
|
return _value;
|
|
}
|
|
alias get this;
|
|
}
|
|
|
|
class C7808 {}
|
|
struct S7808 { C7808 c; }
|
|
|
|
void func7808(S7808 s) {}
|
|
|
|
void test7808()
|
|
{
|
|
auto s = Nullable7808!S7808(S7808(new C7808));
|
|
func7808(s);
|
|
}
|
|
|
|
/***************************************************/
|
|
// 7945
|
|
|
|
struct S7945
|
|
{
|
|
int v;
|
|
alias v this;
|
|
}
|
|
void foo7945(ref int n){}
|
|
|
|
void test7945()
|
|
{
|
|
auto s = S7945(1);
|
|
foo7945(s); // 1.NG -> OK
|
|
s.foo7945(); // 2.OK, ufcs
|
|
foo7945(s.v); // 3.OK
|
|
s.v.foo7945(); // 4.OK, ufcs
|
|
}
|
|
|
|
/***************************************************/
|
|
// 15674 - alias this on out parameter, consistent with 7945 case
|
|
|
|
struct S15674
|
|
{
|
|
int v;
|
|
alias v this;
|
|
}
|
|
void foo15674(out int i){ i = 42; }
|
|
|
|
void test15674()
|
|
{
|
|
S15674 s;
|
|
s.v = 1; foo15674(s); assert(s.v == 42);
|
|
s.v = 1; foo15674(s.v); assert(s.v == 42);
|
|
s.v = 1; s.foo15674(); assert(s.v == 42);
|
|
s.v = 1; s.v.foo15674(); assert(s.v == 42);
|
|
}
|
|
|
|
/***************************************************/
|
|
// 7979
|
|
|
|
void test7979()
|
|
{
|
|
static struct N
|
|
{
|
|
int val;
|
|
alias val this;
|
|
}
|
|
N n = N(1);
|
|
|
|
switch (n)
|
|
{
|
|
case 0:
|
|
assert(0);
|
|
case 1:
|
|
break;
|
|
default:
|
|
assert(0);
|
|
}
|
|
|
|
static struct S
|
|
{
|
|
string val;
|
|
alias val this;
|
|
}
|
|
S s = S("b");
|
|
|
|
switch (s)
|
|
{
|
|
case "a":
|
|
assert(0);
|
|
case "b":
|
|
break;
|
|
default:
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
/***************************************************/
|
|
// 7992
|
|
|
|
struct S7992
|
|
{
|
|
int[] arr;
|
|
alias arr this;
|
|
}
|
|
S7992 func7992(...)
|
|
{
|
|
S7992 ret;
|
|
ret.arr.length = _arguments.length;
|
|
return ret;
|
|
}
|
|
void test7992()
|
|
{
|
|
int[] arr;
|
|
assert(arr.length == 0);
|
|
arr ~= func7992(1, 2); //NG
|
|
//arr = func7992(1, 2); //OK
|
|
assert(arr.length == 2);
|
|
}
|
|
|
|
/***************************************************/
|
|
// 8169
|
|
|
|
void test8169()
|
|
{
|
|
static struct ValueImpl
|
|
{
|
|
static immutable(int) getValue()
|
|
{
|
|
return 42;
|
|
}
|
|
}
|
|
|
|
static struct ValueUser
|
|
{
|
|
ValueImpl m_valueImpl;
|
|
alias m_valueImpl this;
|
|
}
|
|
|
|
static assert(ValueImpl.getValue() == 42); // #0, OK
|
|
static assert(ValueUser.getValue() == 42); // #1, NG -> OK
|
|
static assert( ValueUser.m_valueImpl .getValue() == 42); // #2, NG -> OK
|
|
static assert(typeof(ValueUser.m_valueImpl).getValue() == 42); // #3, OK
|
|
}
|
|
|
|
/***************************************************/
|
|
// 8735
|
|
|
|
struct S8735(alias Arg)
|
|
{
|
|
alias Arg Val;
|
|
alias Val this;
|
|
}
|
|
|
|
struct Tuple9709(T...)
|
|
{
|
|
alias T expand;
|
|
alias expand this;
|
|
}
|
|
|
|
void test8735()
|
|
{
|
|
alias S8735!1 S;
|
|
S s;
|
|
int n = s;
|
|
assert(n == 1);
|
|
|
|
// 11502 case
|
|
static void f(int i);
|
|
S8735!f sf;
|
|
|
|
// 9709 case
|
|
alias A = Tuple9709!(1,int,"foo");
|
|
A a;
|
|
//static assert(A[0] == 1);
|
|
static assert(a[0] == 1);
|
|
//static assert(is(A[1] == int));
|
|
//static assert(is(a[1] == int));
|
|
//static assert(A[2] == "foo");
|
|
static assert(a[2] == "foo");
|
|
}
|
|
|
|
/***************************************************/
|
|
// 9174
|
|
|
|
void test9174()
|
|
{
|
|
static struct Foo
|
|
{
|
|
char x;
|
|
alias x this;
|
|
}
|
|
static assert(is(typeof(true ? 'A' : Foo()) == char));
|
|
static assert(is(typeof(true ? Foo() : 100) == int));
|
|
}
|
|
|
|
/***************************************************/
|
|
// 9177
|
|
|
|
struct S9177
|
|
{
|
|
int foo(int){ return 0; }
|
|
alias foo this;
|
|
}
|
|
pragma(msg, is(S9177 : int));
|
|
|
|
/***************************************************/
|
|
// 9858
|
|
|
|
struct S9858()
|
|
{
|
|
@property int get() const
|
|
{
|
|
return 42;
|
|
}
|
|
alias get this;
|
|
void opAssign(int) {}
|
|
}
|
|
void test9858()
|
|
{
|
|
const S9858!() s;
|
|
int i = s;
|
|
}
|
|
|
|
/***************************************************/
|
|
// 9873
|
|
|
|
void test9873()
|
|
{
|
|
struct Tup(T...) { T field; alias field this; }
|
|
|
|
auto seq1 = Seq!(1, "hi");
|
|
assert(Seq!(1, "hi") == Seq!(1, "hi"));
|
|
assert(seq1 == Seq!(1, "hi"));
|
|
assert(Seq!(1, "hi") == seq1);
|
|
assert(seq1 == seq1);
|
|
|
|
auto seq2 = Seq!(2, "hi");
|
|
assert(Seq!(1, "hi") != Seq!(2, "hi"));
|
|
assert(seq2 != Seq!(1, "hi"));
|
|
assert(Seq!(1, "hi") != seq2);
|
|
assert(seq2 != seq1);
|
|
|
|
auto tup1 = Tup!(int, string)(1, "hi");
|
|
assert(Seq!(1, "hi") == tup1);
|
|
assert(seq1 == tup1);
|
|
assert(tup1 == Seq!(1, "hi"));
|
|
assert(tup1 == seq1);
|
|
|
|
auto tup2 = Tup!(int, string)(2, "hi");
|
|
assert(Seq!(1, "hi") != tup2);
|
|
assert(seq1 != tup2);
|
|
assert(tup2 != Seq!(1, "hi"));
|
|
assert(tup2 != seq1);
|
|
|
|
static assert(!__traits(compiles, seq1 == Seq!(1, "hi", [1,2])));
|
|
static assert(!__traits(compiles, tup1 == Seq!(1, "hi", [1,2])));
|
|
}
|
|
|
|
/***************************************************/
|
|
// 10178
|
|
|
|
void test10178()
|
|
{
|
|
struct S { static int count; }
|
|
S s;
|
|
assert((s.tupleof == s.tupleof) == true);
|
|
assert((s.tupleof != s.tupleof) == false);
|
|
|
|
S getS()
|
|
{
|
|
S s;
|
|
++S.count;
|
|
return s;
|
|
}
|
|
assert(getS().tupleof == getS().tupleof);
|
|
assert(S.count == 2);
|
|
}
|
|
|
|
/***************************************************/
|
|
// 10179
|
|
|
|
void test10179()
|
|
{
|
|
struct S { static int count; }
|
|
S s;
|
|
static assert(s.tupleof.length == 0);
|
|
s.tupleof = s.tupleof; // error -> OK
|
|
|
|
S getS()
|
|
{
|
|
S s;
|
|
++S.count;
|
|
return s;
|
|
}
|
|
getS().tupleof = getS().tupleof;
|
|
assert(S.count == 2);
|
|
}
|
|
|
|
/***************************************************/
|
|
// 9890
|
|
|
|
void test9890()
|
|
{
|
|
struct RefCounted(T)
|
|
{
|
|
T _payload;
|
|
|
|
ref T refCountedPayload()
|
|
{
|
|
return _payload;
|
|
}
|
|
|
|
alias refCountedPayload this;
|
|
}
|
|
|
|
struct S(int x_)
|
|
{
|
|
alias x_ x;
|
|
}
|
|
|
|
alias RefCounted!(S!1) Rs;
|
|
static assert(Rs.x == 1);
|
|
}
|
|
|
|
/***************************************************/
|
|
// 10004
|
|
|
|
void test10004()
|
|
{
|
|
static int count = 0;
|
|
|
|
static S make(S)()
|
|
{
|
|
++count; // necessary to make this function impure
|
|
S s;
|
|
return s;
|
|
}
|
|
|
|
struct SX(T...) {
|
|
T field; alias field this;
|
|
}
|
|
alias S = SX!(int, long);
|
|
assert(make!S.field == make!S.field);
|
|
assert(count == 2);
|
|
}
|
|
|
|
/***************************************************/
|
|
// 10180
|
|
|
|
template TypeTuple10180(TL...) { alias TypeTuple10180 = TL; }
|
|
|
|
template Identity10180(alias T) { alias Identity10180 = T; }
|
|
|
|
struct Tuple10180(Specs...)
|
|
{
|
|
static if (is(Specs))
|
|
{
|
|
alias Types = Specs;
|
|
Types expand;
|
|
alias expand this;
|
|
}
|
|
else
|
|
{
|
|
alias Types = TypeTuple10180!(Specs[0]);
|
|
Types expand;
|
|
mixin("alias Identity10180!(expand[0]) "~Specs[1]~";");
|
|
|
|
@property
|
|
ref Tuple10180!(Specs[0]) _Tuple_super()
|
|
{
|
|
return *cast(typeof(return)*) (&expand[0]);
|
|
}
|
|
alias _Tuple_super this;
|
|
}
|
|
}
|
|
|
|
void test10180()
|
|
{
|
|
Tuple10180!(int, "a") x;
|
|
auto o1 = x.a.offsetof; // OK
|
|
auto o2 = x[0].offsetof; // NG: no property 'offsetof' for type 'int'
|
|
auto o3 = x._Tuple_super[0].offsetof; // same as above
|
|
assert(o2 == o3);
|
|
}
|
|
|
|
/***************************************************/
|
|
// 10456
|
|
|
|
void test10456()
|
|
{
|
|
S10456 s1, s2;
|
|
auto x = s1 == s2;
|
|
}
|
|
|
|
struct S10456
|
|
{
|
|
enum E { e };
|
|
alias E this;
|
|
int[] x;
|
|
}
|
|
|
|
/***************************************************/
|
|
// 11261
|
|
|
|
template Tuple11261(Specs...)
|
|
{
|
|
struct Tuple11261
|
|
{
|
|
static if (Specs.length != 4) // anonymous field version
|
|
{
|
|
alias Specs Types;
|
|
Types expand;
|
|
alias expand this;
|
|
}
|
|
else
|
|
{
|
|
alias Seq!(Specs[0], Specs[2]) Types;
|
|
Types expand;
|
|
ref inout(Tuple11261!Types) _Tuple_super() inout @trusted
|
|
{
|
|
return *cast(typeof(return)*) &(expand[0]);
|
|
}
|
|
// This is mostly to make t[n] work.
|
|
alias _Tuple_super this;
|
|
}
|
|
|
|
this()(Types values)
|
|
{
|
|
expand[] = values[];
|
|
}
|
|
}
|
|
}
|
|
|
|
interface InputRange11261(E)
|
|
{
|
|
@property bool empty();
|
|
@property E front();
|
|
void popFront();
|
|
|
|
int opApply(int delegate(E));
|
|
int opApply(int delegate(size_t, E));
|
|
|
|
}
|
|
template InputRangeObject11261(R)
|
|
{
|
|
alias typeof(R.init.front()) E;
|
|
|
|
class InputRangeObject11261 : InputRange11261!E
|
|
{
|
|
private R _range;
|
|
|
|
this(R range) { this._range = range; }
|
|
|
|
@property bool empty() { return _range.empty; }
|
|
@property E front() { return _range.front; }
|
|
void popFront() { _range.popFront(); }
|
|
|
|
int opApply(int delegate(E) dg) { return 0; }
|
|
int opApply(int delegate(size_t, E) dg) { return 0; }
|
|
}
|
|
}
|
|
|
|
// ------
|
|
|
|
class Container11261
|
|
{
|
|
alias Tuple11261!(string, "key", string, "value") Key;
|
|
|
|
InputRange11261!Key opSlice()
|
|
{
|
|
Range r;
|
|
return new InputRangeObject11261!Range(r);
|
|
}
|
|
private struct Range
|
|
{
|
|
enum empty = false;
|
|
auto popFront() {}
|
|
auto front() { return Key("myKey", "myValue"); }
|
|
}
|
|
}
|
|
|
|
void test11261()
|
|
{
|
|
auto container = new Container11261();
|
|
foreach (k, v; container) // map the tuple of container[].front to (k, v)
|
|
{
|
|
static assert(is(typeof(k) == string) && is(typeof(v) == string));
|
|
break;
|
|
}
|
|
}
|
|
|
|
/***************************************************/
|
|
// 11333
|
|
|
|
alias id11333(a...) = a;
|
|
|
|
struct Unit11333
|
|
{
|
|
enum value = Unit11333.init.tupleof;
|
|
alias value this;
|
|
}
|
|
|
|
void test11333()
|
|
{
|
|
void foo() {}
|
|
|
|
id11333!() unit;
|
|
unit = unit; // ok
|
|
foo(unit); // ok
|
|
|
|
unit = Unit11333.value; // ok
|
|
foo(Unit11333.value); // ok
|
|
|
|
Unit11333 unit2;
|
|
unit = unit2; // ok <- segfault
|
|
}
|
|
|
|
/***************************************************/
|
|
// 11800
|
|
|
|
struct A11800
|
|
{
|
|
B11800 b;
|
|
alias b this;
|
|
}
|
|
|
|
struct B11800
|
|
{
|
|
static struct Value {}
|
|
Value value;
|
|
alias value this;
|
|
|
|
void foo(ref const B11800 rhs)
|
|
{
|
|
}
|
|
}
|
|
|
|
void test11800()
|
|
{
|
|
A11800 a;
|
|
B11800 b;
|
|
b.foo(a);
|
|
}
|
|
|
|
/***************************************************/
|
|
// 12008
|
|
|
|
struct RefCounted12008(T)
|
|
{
|
|
struct RefCountedStore
|
|
{
|
|
private struct Impl
|
|
{
|
|
T _payload;
|
|
}
|
|
|
|
private void initialize(A...)(auto ref A args)
|
|
{
|
|
import core.memory;
|
|
}
|
|
|
|
void ensureInitialized()
|
|
{
|
|
initialize();
|
|
}
|
|
|
|
}
|
|
RefCountedStore _refCounted;
|
|
|
|
void opAssign(T rhs)
|
|
{
|
|
}
|
|
|
|
int refCountedPayload()
|
|
{
|
|
_refCounted.ensureInitialized();
|
|
return 0;
|
|
}
|
|
|
|
int refCountedPayload() inout
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
alias refCountedPayload this;
|
|
}
|
|
|
|
struct SharedInput12008
|
|
{
|
|
Group12008 unused;
|
|
}
|
|
|
|
struct Group12008
|
|
{
|
|
RefCounted12008!SharedInput12008 _allGroups;
|
|
}
|
|
|
|
/***************************************************/
|
|
// 12038
|
|
|
|
bool f12038(void* p) { return true; }
|
|
|
|
struct S12038
|
|
{
|
|
@property p() { f12038(&this); }
|
|
alias p this;
|
|
}
|
|
|
|
/***************************************************/
|
|
// 13490
|
|
|
|
struct S13490
|
|
{
|
|
int i;
|
|
alias i this;
|
|
}
|
|
|
|
struct T13490
|
|
{
|
|
S13490[] a1, a2;
|
|
}
|
|
|
|
void test13490()
|
|
{
|
|
T13490 t;
|
|
|
|
(true ? t.a1 : t.a2) ~= S13490(1);
|
|
assert(t.a1 == [S13490(1)]);
|
|
assert(t.a2 == []);
|
|
|
|
(false ? t.a1 : t.a2) ~= S13490(2);
|
|
assert(t.a1 == [S13490(1)]);
|
|
assert(t.a2 == [S13490(2)]);
|
|
}
|
|
|
|
/***************************************************/
|
|
// 11355
|
|
|
|
struct A11355
|
|
{
|
|
static int postblit;
|
|
this(this) { ++postblit; }
|
|
}
|
|
|
|
struct B11355
|
|
{
|
|
A11355 a;
|
|
alias a this;
|
|
}
|
|
|
|
B11355 make11355()
|
|
{
|
|
return B11355();
|
|
}
|
|
void test11355()
|
|
{
|
|
A11355 a1 = make11355();
|
|
assert(A11355.postblit == 1);
|
|
}
|
|
|
|
/***************************************************/
|
|
// 13009
|
|
|
|
struct T13009
|
|
{
|
|
void put(char c) {}
|
|
}
|
|
|
|
struct S13009(bool rev)
|
|
{
|
|
T13009 t;
|
|
|
|
static if (!rev)
|
|
{
|
|
@property T13009 getT() { return t; }
|
|
@property inout(T13009) getT() inout { return t; }
|
|
}
|
|
else
|
|
{
|
|
@property inout(T13009) getT() inout { return t; }
|
|
@property T13009 getT() { return t; }
|
|
}
|
|
|
|
alias getT this;
|
|
}
|
|
|
|
void test13009()
|
|
{
|
|
foreach (bool rev; Seq!(false, true))
|
|
{
|
|
alias S = S13009!rev;
|
|
|
|
alias MS = S;
|
|
alias CS = const(S);
|
|
alias WS = inout( S);
|
|
alias WCS = inout(const S);
|
|
alias SMS = shared( S);
|
|
alias SCS = shared( const S);
|
|
alias SWS = shared(inout S);
|
|
alias SWCS = shared(inout const S);
|
|
alias IS = immutable(S);
|
|
|
|
alias MSput = MS .put;
|
|
alias CSput = CS .put;
|
|
alias WSput = WS .put;
|
|
alias WCSput = WCS.put;
|
|
static assert(!__traits(compiles, { alias SMSput = SMS .put; }));
|
|
static assert(!__traits(compiles, { alias SCSput = SCS .put; }));
|
|
static assert(!__traits(compiles, { alias SWSput = SWS .put; }));
|
|
static assert(!__traits(compiles, { alias SWCSput = SWCS.put; }));
|
|
alias ISput = IS .put;
|
|
}
|
|
}
|
|
|
|
/***************************************************/
|
|
// 14806
|
|
|
|
struct Nullable14806
|
|
{
|
|
float get() { return float.nan; }
|
|
alias get this;
|
|
}
|
|
|
|
struct Foo14806(T)
|
|
{
|
|
T bar;
|
|
Nullable14806 baz;
|
|
}
|
|
|
|
void test14806()
|
|
{
|
|
Foo14806!int a, b;
|
|
assert(a != b);
|
|
// ==> a.tupleof != b.tupleof
|
|
// ==> a.bar != b.bar || a.baz.get() != b.baz.get()
|
|
|
|
Foo14806!string c, d;
|
|
assert(c != d);
|
|
// ==> c.tupleof != d.tupleof
|
|
// ==> c.bar != d.bar || c.baz.get() != d.baz.get()
|
|
}
|
|
|
|
/***************************************************/
|
|
// 14948
|
|
|
|
struct RefCounted14948(T)
|
|
{
|
|
struct Impl
|
|
{
|
|
T data;
|
|
}
|
|
Impl* impl;
|
|
|
|
@property ref T payload() { return impl.data; }
|
|
|
|
alias payload this;
|
|
}
|
|
|
|
struct HTTP14948
|
|
{
|
|
struct Impl
|
|
{
|
|
}
|
|
|
|
RefCounted14948!Impl p;
|
|
}
|
|
|
|
void test14948()
|
|
{
|
|
int[HTTP14948] aa;
|
|
}
|
|
|
|
/***************************************************/
|
|
// 15292
|
|
|
|
struct NullableRef15292(T)
|
|
{
|
|
inout(T) get() inout
|
|
{
|
|
assert(false);
|
|
}
|
|
|
|
alias get this;
|
|
}
|
|
|
|
struct S15292
|
|
{
|
|
NullableRef15292!S15292 n; // -> no segfault
|
|
|
|
/* The field 'n' contains alias this, so to use it for the equality,
|
|
* following helper function is automatically generated in buildXopEquals().
|
|
*
|
|
* static bool __xopEquals(ref const S15292 p, ref const S15292 q)
|
|
* {
|
|
* return p == q;
|
|
* }
|
|
*
|
|
* In its definition, const(S15292) equality is analyzed. It fails, then
|
|
* the error is gagged.
|
|
*/
|
|
}
|
|
|
|
/***************************************************/
|
|
|
|
int main()
|
|
{
|
|
test1();
|
|
test2();
|
|
test3();
|
|
test4();
|
|
test5();
|
|
test4617a();
|
|
test4617b();
|
|
test4773();
|
|
test5188();
|
|
test6();
|
|
test7();
|
|
test2781();
|
|
test6546();
|
|
test6736();
|
|
test2777a();
|
|
test2777b();
|
|
test5679();
|
|
test6508();
|
|
test6508x();
|
|
test6369a();
|
|
test6369b();
|
|
test6369c();
|
|
test6369d();
|
|
test6434();
|
|
test6366();
|
|
test6711();
|
|
test12161();
|
|
test6759();
|
|
test6832();
|
|
test6928();
|
|
test6929();
|
|
test7136();
|
|
test7731();
|
|
test7808();
|
|
test7945();
|
|
test15674();
|
|
test7979();
|
|
test7992();
|
|
test8169();
|
|
test8735();
|
|
test9174();
|
|
test9858();
|
|
test9873();
|
|
test10178();
|
|
test10179();
|
|
test9890();
|
|
test10004();
|
|
test10180();
|
|
test10456();
|
|
test11333();
|
|
test11800();
|
|
test13490();
|
|
test11355();
|
|
test14806();
|
|
|
|
printf("Success\n");
|
|
return 0;
|
|
}
|