1 /**
2  * Compiler capability detection
3  *
4  * License:
5  *   This Source Code Form is subject to the terms of
6  *   the Mozilla Public License, v. 2.0. If a copy of
7  *   the MPL was not distributed with this file, You
8  *   can obtain one at http://mozilla.org/MPL/2.0/.
9  *
10  * Authors:
11  *   Vladimir Panteleev <vladimir@thecybershadow.net>
12  */
13 
14 module ae.utils.meta.caps;
15 
16 /// Does this compiler support __traits(child) ?
17 /// https://github.com/D-Programming-Language/dmd/pull/3329
18 enum haveChildTrait = is(typeof({ struct S { int i; } S s; __traits(child, s, S.i) = 0; }));
19 
20 // ************************************************************************
21 
22 struct TestFieldAliasBinding
23 {
24 	static template T(alias a)
25 	{
26 		void foo()() { a = 0; }
27 	}
28 
29 	struct S(alias T)
30 	{
31 		int f;
32 		alias t = T!f;
33 	}
34 
35 	static void test()()
36 	{
37 		S!T s;
38 		s.t.foo();
39 	}
40 }
41 
42 /// Does this compiler support binding field context via alias parameters?
43 /// https://github.com/D-Programming-Language/dmd/pull/2794
44 /// Added   in 2.065.0: https://github.com/D-Programming-Language/dmd/pull/2794
45 /// Removed in 2.066.1: https://github.com/D-Programming-Language/dmd/pull/3884
46 enum haveFieldAliasBinding = __traits(compiles, TestFieldAliasBinding.test());
47 
48 // ************************************************************************
49 
50 struct TestMethodAliasBinding
51 {
52 	static template T(alias a)
53 	{
54 		void foo()() { a(); }
55 	}
56 
57 	struct S(alias T)
58 	{
59 		void m() { }
60 		alias t = T!m;
61 	}
62 
63 	static void test()()
64 	{
65 		S!T s;
66 		s.t.foo();
67 	}
68 }
69 
70 /// Does this compiler support binding method context via alias parameters?
71 /// https://github.com/D-Programming-Language/dmd/pull/3345
72 enum haveMethodAliasBinding = __traits(compiles, TestMethodAliasBinding.test());
73 
74 // ************************************************************************
75 
76 struct TestAliasCtxInference
77 {
78 	struct A
79 	{
80 		void fun() {}
81 
82 		void caller(T)(T t)
83 		{
84 			t.callee();
85 		}
86 	}
87 
88 	struct B
89 	{
90 		alias callee = A.fun;
91 	}
92 
93 	static void test()()
94 	{
95 		A a;
96 		B b;
97 		a.caller(b);
98 	}
99 }
100 
101 /// Does this compiler support inferring "this" of an aliased
102 /// method call from the current context?
103 /// https://github.com/D-Programming-Language/dmd/pull/3361
104 enum haveAliasCtxInference = __traits(compiles, TestAliasCtxInference.test());
105 
106 // ************************************************************************
107 
108 struct TestAliasStructBinding
109 {
110 	struct S(alias fun)
111 	{
112 		void call(T)(T t)
113 		{
114 			fun(t);
115 		}
116 	}
117 
118 	static void test()()
119 	{
120 		int n;
121 
122 		// Hmm, why doesn't this work?
123 		//void fun(T)(T x) { n += x; }
124 		//S!fun s;
125 
126 		S!(x => n+=x) s;
127 		s.call(42);
128 	}
129 }
130 
131 /// Does this compiler support binding lambdas via struct template alias parameters?
132 /// https://github.com/dlang/dmd/pull/5518
133 enum haveAliasStructBinding = __traits(compiles, TestAliasStructBinding.test());
134 
135 // ************************************************************************
136 
137 struct TestDualContext
138 {
139 	struct S
140 	{
141 		int i;
142 		void call(alias f)()
143 		{
144 			f(i);
145 		}
146 	}
147 
148 	static void test()()
149 	{
150 		int n;
151 		void fun(int i) { n = i; }
152 		S s;
153 		s.call!fun();
154 	}
155 }
156 
157 /// Does this compiler support dual context pointers?
158 /// https://github.com/dlang/dmd/pull/9282
159 version (DMD)
160 	enum haveDualContext = __traits(compiles, TestDualContext.test());
161 else
162 	enum haveDualContext = false; // https://github.com/ldc-developers/ldc/commit/d93087ad90664e9be87b79cf70c0f3d26f30f107#commitcomment-35276701
163 
164 // ************************************************************************
165 
166 enum haveStaticForeach = is(typeof(mixin(q{(){ static foreach (x; []) {}}})));