| /* |
| runnable/traits.d 9091,8972,8971,7027 |
| runnable/test4.d test6() |
| RUN_OUTPUT: |
| --- |
| Success |
| --- |
| */ |
| |
| extern(C) int printf(const char*, ...); |
| |
| template TypeTuple(TL...) { alias TypeTuple = TL; } |
| |
| /********************************************************/ |
| |
| mixin("struct S1 {"~aggrDecl1~"}"); |
| mixin("class C1 {"~aggrDecl1~"}"); |
| enum aggrDecl1 = |
| q{ |
| alias Type = typeof(this); |
| |
| int x = 2; |
| |
| void foo() |
| { |
| static assert( is(typeof(Type.x.offsetof))); |
| static assert( is(typeof(Type.x.mangleof))); |
| static assert( is(typeof(Type.x.sizeof ))); |
| static assert( is(typeof(Type.x.alignof ))); |
| static assert( is(typeof({ auto n = Type.x.offsetof; }))); |
| static assert( is(typeof({ auto n = Type.x.mangleof; }))); |
| static assert( is(typeof({ auto n = Type.x.sizeof; }))); |
| static assert( is(typeof({ auto n = Type.x.alignof; }))); |
| static assert( is(typeof(Type.x))); |
| static assert( is(typeof({ auto n = Type.x; }))); |
| static assert( __traits(compiles, Type.x)); |
| static assert( __traits(compiles, { auto n = Type.x; })); |
| |
| static assert( is(typeof(x.offsetof))); |
| static assert( is(typeof(x.mangleof))); |
| static assert( is(typeof(x.sizeof ))); |
| static assert( is(typeof(x.alignof ))); |
| static assert( is(typeof({ auto n = x.offsetof; }))); |
| static assert( is(typeof({ auto n = x.mangleof; }))); |
| static assert( is(typeof({ auto n = x.sizeof; }))); |
| static assert( is(typeof({ auto n = x.alignof; }))); |
| static assert( is(typeof(x))); |
| static assert( is(typeof({ auto n = x; }))); |
| static assert( __traits(compiles, x)); |
| static assert( __traits(compiles, { auto n = x; })); |
| |
| with (this) |
| { |
| static assert( is(typeof(x.offsetof))); |
| static assert( is(typeof(x.mangleof))); |
| static assert( is(typeof(x.sizeof ))); |
| static assert( is(typeof(x.alignof ))); |
| static assert( is(typeof({ auto n = x.offsetof; }))); |
| static assert( is(typeof({ auto n = x.mangleof; }))); |
| static assert( is(typeof({ auto n = x.sizeof; }))); |
| static assert( is(typeof({ auto n = x.alignof; }))); |
| static assert( is(typeof(x))); |
| static assert( is(typeof({ auto n = x; }))); |
| static assert( __traits(compiles, x)); |
| static assert( __traits(compiles, { auto n = x; })); |
| } |
| } |
| |
| static void bar() |
| { |
| static assert( is(typeof(Type.x.offsetof))); |
| static assert( is(typeof(Type.x.mangleof))); |
| static assert( is(typeof(Type.x.sizeof ))); |
| static assert( is(typeof(Type.x.alignof ))); |
| static assert( is(typeof({ auto n = Type.x.offsetof; }))); |
| static assert( is(typeof({ auto n = Type.x.mangleof; }))); |
| static assert( is(typeof({ auto n = Type.x.sizeof; }))); |
| static assert( is(typeof({ auto n = Type.x.alignof; }))); |
| static assert( is(typeof(Type.x))); |
| static assert(!is(typeof({ auto n = Type.x; }))); |
| static assert( __traits(compiles, Type.x)); |
| static assert(!__traits(compiles, { auto n = Type.x; })); |
| |
| static assert( is(typeof(x.offsetof))); |
| static assert( is(typeof(x.mangleof))); |
| static assert( is(typeof(x.sizeof ))); |
| static assert( is(typeof(x.alignof ))); |
| static assert( is(typeof({ auto n = x.offsetof; }))); |
| static assert( is(typeof({ auto n = x.mangleof; }))); |
| static assert( is(typeof({ auto n = x.sizeof; }))); |
| static assert( is(typeof({ auto n = x.alignof; }))); |
| static assert( is(typeof(x))); |
| static assert(!is(typeof({ auto n = x; }))); |
| static assert( __traits(compiles, x)); |
| static assert(!__traits(compiles, { auto n = x; })); |
| |
| Type t; |
| with (t) |
| { |
| static assert( is(typeof(x.offsetof))); |
| static assert( is(typeof(x.mangleof))); |
| static assert( is(typeof(x.sizeof ))); |
| static assert( is(typeof(x.alignof ))); |
| static assert( is(typeof({ auto n = x.offsetof; }))); |
| static assert( is(typeof({ auto n = x.mangleof; }))); |
| static assert( is(typeof({ auto n = x.sizeof; }))); |
| static assert( is(typeof({ auto n = x.alignof; }))); |
| static assert( is(typeof(x))); |
| static assert( is(typeof({ auto n = x; }))); |
| static assert( __traits(compiles, x)); |
| static assert( __traits(compiles, { auto n = x; })); |
| } |
| } |
| }; |
| void test1() |
| { |
| foreach (Type; TypeTuple!(S1, C1)) |
| { |
| static assert( is(typeof(Type.x.offsetof))); |
| static assert( is(typeof(Type.x.mangleof))); |
| static assert( is(typeof(Type.x.sizeof ))); |
| static assert( is(typeof(Type.x.alignof ))); |
| static assert( is(typeof({ auto n = Type.x.offsetof; }))); |
| static assert( is(typeof({ auto n = Type.x.mangleof; }))); |
| static assert( is(typeof({ auto n = Type.x.sizeof; }))); |
| static assert( is(typeof({ auto n = Type.x.alignof; }))); |
| static assert( is(typeof(Type.x))); |
| static assert(!is(typeof({ auto n = Type.x; }))); |
| static assert( __traits(compiles, Type.x)); |
| static assert(!__traits(compiles, { auto n = Type.x; })); |
| |
| Type t; |
| static assert( is(typeof(t.x.offsetof))); |
| static assert( is(typeof(t.x.mangleof))); |
| static assert( is(typeof(t.x.sizeof ))); |
| static assert( is(typeof(t.x.alignof ))); |
| static assert( is(typeof({ auto n = t.x.offsetof; }))); |
| static assert( is(typeof({ auto n = t.x.mangleof; }))); |
| static assert( is(typeof({ auto n = t.x.sizeof; }))); |
| static assert( is(typeof({ auto n = t.x.alignof; }))); |
| static assert( is(typeof(t.x))); |
| static assert( is(typeof({ auto n = t.x; }))); |
| static assert( __traits(compiles, t.x)); |
| static assert( __traits(compiles, { auto n = t.x; })); |
| |
| with (t) |
| { |
| static assert( is(typeof(x.offsetof))); |
| static assert( is(typeof(x.mangleof))); |
| static assert( is(typeof(x.sizeof ))); |
| static assert( is(typeof(x.alignof ))); |
| static assert( is(typeof({ auto n = x.offsetof; }))); |
| static assert( is(typeof({ auto n = x.mangleof; }))); |
| static assert( is(typeof({ auto n = x.sizeof; }))); |
| static assert( is(typeof({ auto n = x.alignof; }))); |
| static assert( is(typeof(x))); |
| static assert( is(typeof({ auto n = x; }))); |
| static assert( __traits(compiles, x)); |
| static assert( __traits(compiles, { auto n = x; })); |
| } |
| } |
| } |
| |
| /********************************************************/ |
| |
| void test2() |
| { |
| struct S |
| { |
| int val; |
| int[] arr; |
| int[int] aar; |
| |
| void foo() {} |
| void boo()() {} |
| |
| static void test() |
| { |
| static assert(!__traits(compiles, S.foo())); |
| static assert(!__traits(compiles, S.boo())); |
| static assert(!__traits(compiles, foo())); |
| static assert(!__traits(compiles, boo())); |
| } |
| } |
| int v; |
| int[] a; |
| void f(int n) {} |
| |
| static assert( __traits(compiles, S.val)); // 'S.val' is treated just a symbol |
| static assert(!__traits(compiles, { int n = S.val; })); |
| static assert(!__traits(compiles, f(S.val))); |
| |
| static assert(!__traits(compiles, v = S.val) && !__traits(compiles, S.val = v)); |
| |
| static assert(!__traits(compiles, 1 + S.val) && !__traits(compiles, S.val + 1)); |
| static assert(!__traits(compiles, 1 - S.val) && !__traits(compiles, S.val - 1)); |
| static assert(!__traits(compiles, 1 * S.val) && !__traits(compiles, S.val * 1)); |
| static assert(!__traits(compiles, 1 / S.val) && !__traits(compiles, S.val / 1)); |
| static assert(!__traits(compiles, 1 % S.val) && !__traits(compiles, S.val % 1)); |
| static assert(!__traits(compiles, 1 ~ S.arr) && !__traits(compiles, S.arr ~ 1)); |
| |
| static assert(!__traits(compiles, 1 & S.val) && !__traits(compiles, S.val & 1)); |
| static assert(!__traits(compiles, 1 | S.val) && !__traits(compiles, S.val | 1)); |
| static assert(!__traits(compiles, 1 ^ S.val) && !__traits(compiles, S.val ^ 1)); |
| static assert(!__traits(compiles, 1 ~ S.val) && !__traits(compiles, S.val ~ 1)); |
| |
| static assert(!__traits(compiles, 1 ^^ S.val) && !__traits(compiles, S.val ^^ 1)); |
| static assert(!__traits(compiles, 1 << S.val) && !__traits(compiles, S.val << 1)); |
| static assert(!__traits(compiles, 1 >> S.val) && !__traits(compiles, S.val >> 1)); |
| static assert(!__traits(compiles, 1 >>>S.val) && !__traits(compiles, S.val >>>1)); |
| static assert(!__traits(compiles, 1 && S.val) && !__traits(compiles, S.val && 1)); |
| static assert(!__traits(compiles, 1 || S.val) && !__traits(compiles, S.val || 1)); |
| static assert(!__traits(compiles, 1 in S.aar) && !__traits(compiles, S.val || [1:1])); |
| |
| static assert(!__traits(compiles, 1 <= S.val) && !__traits(compiles, S.val <= 1)); |
| static assert(!__traits(compiles, 1 == S.val) && !__traits(compiles, S.val == 1)); |
| static assert(!__traits(compiles, 1 is S.val) && !__traits(compiles, S.val is 1)); |
| |
| static assert(!__traits(compiles, 1? 1:S.val) && !__traits(compiles, 1? S.val:1)); |
| static assert(!__traits(compiles, (1, S.val)) && !__traits(compiles, (S.val, 1))); |
| |
| static assert(!__traits(compiles, &S.val)); |
| static assert(!__traits(compiles, S.arr[0]) && !__traits(compiles, [1,2][S.val])); |
| static assert(!__traits(compiles, S.val++) && !__traits(compiles, S.val--)); |
| static assert(!__traits(compiles, ++S.val) && !__traits(compiles, --S.val)); |
| |
| static assert(!__traits(compiles, v += S.val) && !__traits(compiles, S.val += 1)); |
| static assert(!__traits(compiles, v -= S.val) && !__traits(compiles, S.val -= 1)); |
| static assert(!__traits(compiles, v *= S.val) && !__traits(compiles, S.val *= 1)); |
| static assert(!__traits(compiles, v /= S.val) && !__traits(compiles, S.val /= 1)); |
| static assert(!__traits(compiles, v %= S.val) && !__traits(compiles, S.val %= 1)); |
| static assert(!__traits(compiles, v &= S.val) && !__traits(compiles, S.val &= 1)); |
| static assert(!__traits(compiles, v |= S.val) && !__traits(compiles, S.val |= 1)); |
| static assert(!__traits(compiles, v ^= S.val) && !__traits(compiles, S.val ^= 1)); |
| static assert(!__traits(compiles, a ~= S.val) && !__traits(compiles, S.arr ~= 1)); |
| |
| static assert(!__traits(compiles, v ^^= S.val) && !__traits(compiles, S.val ^^= 1)); |
| static assert(!__traits(compiles, v <<= S.val) && !__traits(compiles, S.val <<= 1)); |
| static assert(!__traits(compiles, v >>= S.val) && !__traits(compiles, S.val >>= 1)); |
| static assert(!__traits(compiles, v >>>=S.val) && !__traits(compiles, S.val >>>=1)); |
| |
| static assert(!__traits(compiles, { auto x = 1 + S.val; }) && !__traits(compiles, { auto x = S.val + 1; })); |
| static assert(!__traits(compiles, { auto x = 1 - S.val; }) && !__traits(compiles, { auto x = S.val - 1; })); |
| static assert(!__traits(compiles, { auto x = S.arr ~ 1; }) && !__traits(compiles, { auto x = 1 ~ S.arr; })); |
| |
| static assert(!__traits(compiles, S.foo())); |
| static assert(!__traits(compiles, S.boo())); |
| S.test(); |
| alias foo = S.foo; |
| alias boo = S.boo; |
| static assert(!__traits(compiles, foo())); |
| static assert(!__traits(compiles, boo())); |
| |
| // static assert(S.val); |
| |
| struct SW { int a; } |
| class CW { int a; } |
| static assert(!__traits(compiles, { with (SW) { int n = a; } })); |
| static assert(!__traits(compiles, { with (CW) { int n = a; } })); |
| } |
| |
| /********************************************************/ |
| |
| struct S3 |
| { |
| struct T3 { int val; void foo() {} } |
| T3 member; |
| alias member this; |
| |
| static void test() |
| { |
| static assert(!__traits(compiles, S3.val = 1 )); |
| static assert(!__traits(compiles, { S3.val = 1; })); |
| static assert(!__traits(compiles, T3.val = 1 )); |
| static assert(!__traits(compiles, { T3.val = 1; })); |
| static assert(!__traits(compiles, __traits(getMember, S3, "val") = 1 )); |
| static assert(!__traits(compiles, { __traits(getMember, S3, "val") = 1; })); |
| static assert(!__traits(compiles, __traits(getMember, T3, "val") = 1 )); |
| static assert(!__traits(compiles, { __traits(getMember, T3, "val") = 1; })); |
| |
| static assert(!__traits(compiles, S3.foo() )); |
| static assert(!__traits(compiles, { S3.foo(); })); |
| static assert(!__traits(compiles, T3.foo() )); |
| static assert(!__traits(compiles, { T3.foo(); })); |
| static assert(!__traits(compiles, __traits(getMember, S3, "foo")() )); |
| static assert(!__traits(compiles, { __traits(getMember, S3, "foo")(); })); |
| static assert(!__traits(compiles, __traits(getMember, T3, "foo")() )); |
| static assert(!__traits(compiles, { __traits(getMember, T3, "foo")(); })); |
| static assert(!__traits(compiles, __traits(getOverloads, S3, "foo")[0]() )); |
| static assert(!__traits(compiles, { __traits(getOverloads, S3, "foo")[0](); })); |
| static assert(!__traits(compiles, __traits(getOverloads, T3, "foo")[0]() )); |
| static assert(!__traits(compiles, { __traits(getOverloads, T3, "foo")[0](); })); |
| } |
| } |
| |
| void test3() |
| { |
| } |
| |
| /********************************************************/ |
| |
| void test4() |
| { |
| static struct R |
| { |
| void opIndex(int) {} |
| void opSlice() {} |
| void opSlice(int, int) {} |
| int opDollar() { return 1; } |
| alias length = opDollar; |
| } |
| |
| R val; |
| static struct S |
| { |
| R val; |
| void foo() |
| { |
| static assert(__traits(compiles, val[1])); // TypeSArray |
| static assert(__traits(compiles, val[])); // TypeDArray |
| static assert(__traits(compiles, val[0..val.length])); // TypeSlice |
| } |
| } |
| } |
| |
| /********************************************************/ |
| |
| template Test5(string name, bool result) |
| { |
| mixin(`static assert(__traits(compiles, `~name~`.add!"months"(1)) == result);`); |
| } |
| |
| static struct Begin5 |
| { |
| void add(string s)(int n) {} |
| } |
| |
| struct IntervalX5(TP) |
| { |
| Begin5 begin; |
| |
| static assert(__traits(compiles, begin.add!"months"(1)) == true); |
| mixin Test5!("begin", true); |
| |
| void foo() |
| { |
| static assert(__traits(compiles, begin.add!"months"(1)) == true); |
| mixin Test5!("begin", true); |
| } |
| static test() |
| { |
| static assert(__traits(compiles, begin.add!"months"(1)) == false); |
| mixin Test5!("begin", false); |
| } |
| } |
| |
| alias IX5 = IntervalX5!int; |
| alias beginX5 = IX5.begin; |
| static assert(__traits(compiles, beginX5.add!"months"(1)) == false); |
| mixin Test5!("beginG5", false); |
| |
| void test5() |
| { |
| static struct IntervalY5(TP) |
| { |
| Begin5 begin; |
| |
| static assert(__traits(compiles, begin.add!"months"(1)) == true); |
| mixin Test5!("begin", true); |
| |
| void foo() |
| { |
| static assert(__traits(compiles, begin.add!"months"(1)) == true); |
| mixin Test5!("begin", true); |
| } |
| static test() |
| { |
| static assert(__traits(compiles, begin.add!"months"(1)) == false); |
| mixin Test5!("begin", false); |
| } |
| } |
| |
| alias IX = IntervalX5!int; |
| alias beginX = IX.begin; |
| static assert(__traits(compiles, beginX.add!"months"(1)) == false); |
| mixin Test5!("beginX", false); |
| |
| alias IY = IntervalY5!int; |
| alias beginY = IY.begin; |
| static assert(__traits(compiles, beginY.add!"months"(1)) == false); |
| mixin Test5!("beginY", false); |
| } |
| |
| /********************************************************/ |
| |
| void test6() |
| { |
| static struct Foo |
| { |
| static struct Bar |
| { |
| static int get() { return 0; } |
| static int val; |
| void set() { assert(0); } |
| int num; |
| } |
| static class Baz |
| { |
| static int get() { return 0; } |
| static int val; |
| void set() { assert(0); } |
| int num; |
| } |
| Bar bar; |
| Baz baz; |
| } |
| |
| // allowed cases that do 'use' Foo.bar without this |
| assert(Foo.bar.get() == 0); // Foo.bar.get() |
| assert(Foo.baz.get() == 0); // Foo.bar.get() |
| static assert(!__traits(compiles, Foo.bar.set())); |
| static assert(!__traits(compiles, Foo.baz.set())); |
| |
| assert(Foo.bar.val == 0); // Foo.bar.val |
| assert(Foo.baz.val == 0); // Foo.baz.val |
| static assert(!__traits(compiles, Foo.bar.num = 1)); |
| static assert(!__traits(compiles, Foo.baz.num = 1)); |
| } |
| |
| /********************************************************/ |
| |
| struct Tuple7(T...) |
| { |
| T field; |
| |
| enum check1 = is(typeof(field[0] = 1)); |
| enum check2 = is(typeof({ field[0] = 1; })); |
| |
| this(U, size_t n)(U[n] values) |
| if (is(typeof({ foreach (i, _; T) field[0] = values[0]; }))) |
| {} |
| } |
| |
| void test7() |
| { |
| alias Tuple7!(int, int) Tup7; |
| static assert(Tup7.check1); |
| static assert(Tup7.check2); |
| int[2] ints = [ 1, 2 ]; |
| Tup7 t = ints; |
| |
| struct S7 |
| { |
| int value; |
| |
| enum check1 = is(typeof(value = 1)); |
| enum check2 = is(typeof({ value = 1; })); |
| |
| void foo()(int v) |
| if (is(typeof({ |
| value = v; // valid |
| }))) {} |
| |
| static void bar()(int v) |
| if (is(typeof({ |
| value = v; // always invalid |
| }))) {} |
| } |
| static assert(S7.check1); |
| static assert(S7.check2); |
| S7 s; |
| s.foo(1); |
| static assert(!__traits(compiles, S7.bar(1))); |
| } |
| |
| /********************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=4350 |
| |
| template Mix4350() { int b; } |
| |
| struct S4350 |
| { |
| int a; |
| |
| mixin Mix4350 mix; |
| |
| int c; |
| template Func() { void call(int n) { c = n; } } |
| alias func = Func!(); |
| } |
| |
| void test4350() |
| { |
| S4350 s; |
| |
| s.a = 1; |
| s.mix.b = 2; |
| s.func.call(3); |
| assert(s.a == 1); |
| assert(s.b == 2); |
| assert(s.c == 3); |
| |
| with (s) { a = 2; } |
| with (s) { mix.b = 3; } |
| with (s) { func.call(4); } |
| assert(s.a == 2); |
| assert(s.b == 3); |
| assert(s.c == 4); |
| } |
| |
| /********************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6430 |
| |
| auto bug6430(int a) |
| { |
| static struct Result2 {} |
| return 4; |
| } |
| auto bug6430(int a, int b) |
| { |
| static struct Result2 |
| { |
| int z; |
| int y() { return z; } |
| } |
| auto t = Result2(1); |
| return 5; |
| } |
| |
| /********************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=9619 |
| |
| struct Foo9619 { int x; } |
| void test9619() |
| { |
| void bar() |
| { |
| typeof(Foo9619.x) y; |
| } |
| } |
| |
| /********************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=9633 |
| |
| class Foo9633 |
| { |
| void baz() {} |
| void bar() |
| { |
| // CallExp::e1->op == TOKvar |
| static assert(!compilesWithoutThis9633!baz); |
| } |
| void vaz()() |
| { |
| static class C |
| { |
| // CallExp::e1->op == TOKtemplate |
| static assert(!__traits(compiles, vaz())); |
| } |
| } |
| } |
| |
| template compilesWithoutThis9633(alias F) |
| { |
| enum bool compilesWithoutThis9633 = __traits(compiles, F()); |
| } |
| |
| void test9633() |
| { |
| auto foo = new Foo9633; |
| foo.bar(); |
| foo.vaz(); |
| } |
| |
| /********************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=11245 |
| |
| struct Vec11245 |
| { |
| float[2] f; |
| } |
| |
| class Bar11245 |
| { |
| void func() |
| { |
| float[Vec11245.f.length] newVal; |
| } |
| } |
| |
| /********************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=11614 |
| |
| struct Tuple11614(T...) |
| { |
| T field; |
| alias field this; |
| } |
| |
| struct Foo11614 |
| { |
| alias Tuple11614!(int) NEW_ARGS; |
| |
| NEW_ARGS args; |
| |
| void foo() |
| { |
| static if (NEW_ARGS.length == 1) |
| {} |
| else |
| static assert(0); |
| } |
| } |
| |
| /********************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=11993 |
| |
| struct S11993 |
| { |
| void foo()() const |
| if (is(typeof(this) == const(S11993))) |
| {} |
| |
| const void bar()() |
| if (is(typeof(this) == const(S11993))) |
| {} |
| } |
| |
| void test11993() |
| { |
| S11993 s; |
| s.foo(); |
| s.bar(); |
| } |
| |
| /********************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=15934 |
| |
| class B15934 |
| { |
| int foo() { return 1; } |
| int foo() const { return 2; } |
| } |
| |
| class C15934 : B15934 |
| { |
| override int foo() { return 3; } |
| override int foo() const { return 4; } |
| |
| void test1() |
| { |
| assert(this.foo() == 3); |
| assert( foo() == 3); |
| assert(this.B15934.foo() == 1); |
| assert( B15934.foo() == 1); |
| } |
| |
| void test2() const |
| { |
| assert(this.foo() == 4); |
| assert( foo() == 4); |
| assert(this.B15934.foo() == 2); // OK <- wrongly returns 1 |
| assert( B15934.foo() == 2); // OK <- wrongly returns 1 |
| } |
| } |
| |
| void test15934() |
| { |
| auto c = new C15934(); |
| c.test1(); |
| c.test2(); |
| } |
| |
| /********************************************************/ |
| |
| int main() |
| { |
| test1(); |
| test2(); |
| test3(); |
| test4(); |
| test5(); |
| test6(); |
| test7(); |
| test4350(); |
| test9619(); |
| test9633(); |
| test15934(); |
| |
| printf("Success\n"); |
| return 0; |
| } |