1 // Written in the D programming language
2 /++
3     Templates which extract information about types and symbols at compile time.
4 
5     In the context of phobos.sys.traits, a "trait" is a template which provides
6     information about a type or symbol. Most traits evaluate to
7     $(D true) or $(D false), telling the code using it whether the given
8     arguments match / have that specific trait (e.g. whether the given type is
9     a dynamic array or whether the given function is $(D @safe)). However, some
10     traits may provide other kinds of information about a type (e.g. the trait
11     could evaluate to the base type for an enum type, or it could strip
12     $(D const) from the type to provide the mutable version of that type).
13 
14     These traits are then used primarily in template constraints so that they
15     can test that the template arguments meet the criteria required by those
16     templates, though they can be useful in a variety of compile-time contexts
17     (e.g. the condition of a $(D static if)).
18 
19     Note that unless otherwise specified, the isXXXX and hasXXX traits in this
20     module are checking for exact matches, so base types (e.g. with enums) and
21     other implicit conversions do not factor into whether such traits are true
22     or false. The type itself is being checked, not what it can be converted
23     to.
24 
25     This is because these traits are often used in templated constraints, and
26     having a type pass a template constraint based on an implicit conversion
27     but then not have the implicit conversion actually take place (which it
28     won't unless the template does something to force it internally) can lead
29     to either compilation errors or subtle behavioral differences - and even
30     when the conversion is done explicitly within a templated function, since
31     it's not done at the call site, it can still lead to subtle bugs in some
32     cases (e.g. if slicing a static array is involved).
33 
34     So, it's typically best to be explicit and clear about a template constraint
35     accepting any kind of implicit conversion rather than having it buried in a
36     trait where programmers stand a good chance of using the trait without
37     realizing that enums might pass based on their base type - or that a type
38     might pass based on some other implicit conversion.
39 
40     Regardless of what a trait is testing for, the documentation strives to be
41     $(I very) clear about what the trait does, and of course, the names do try
42     to make it clear as well - though obviously, only so much information can
43     be put into a name, and some folks will misintrepret some symbols no matter
44     how well they're named. So, please be sure that you clearly understand what
45     these traits do when using them, since messing up template constraints can
46     unfortunately be a great way to introduce subtle bugs into your program.
47     Either way, of course, unit tests are your friends.
48 
49     $(SCRIPT inhibitQuickIndex = 1;)
50 
51     $(BOOKTABLE ,
52     $(TR $(TH Category) $(TH Templates))
53     $(TR $(TD Categories of types) $(TD
54               $(LREF isAggregateType)
55               $(LREF isDynamicArray)
56               $(LREF isFloatingPoint)
57               $(LREF isInstantiationOf)
58               $(LREF isInteger)
59               $(LREF isNumeric)
60               $(LREF isPointer)
61               $(LREF isSignedInteger)
62               $(LREF isStaticArray)
63               $(LREF isType)
64               $(LREF isUnsignedInteger)
65     ))
66     $(TR $(TD Traits testing for type conversions) $(TD
67               $(LREF isImplicitlyConvertible)
68               $(LREF isQualifierConvertible)
69     ))
70     $(TR $(TD Traits for comparisons) $(TD
71               $(LREF isEqual)
72               $(LREF isSameSymbol)
73               $(LREF isSameType)
74     ))
75     $(TR $(TD Function traits) $(TD
76               $(LREF isDelegate)
77               $(LREF isFunction)
78               $(LREF isFunctionPointer)
79               $(LREF isReturn)
80               $(LREF ToFunctionType)
81     ))
82     $(TR $(TD Aggregate Type Traits) $(TD
83               $(LREF FieldNames)
84               $(LREF FieldSymbols)
85               $(LREF FieldTypes)
86               $(LREF hasComplexAssignment)
87               $(LREF hasComplexCopying)
88               $(LREF hasComplexDestruction)
89               $(LREF hasIndirections)
90     ))
91     $(TR $(TD General Types) $(TD
92               $(LREF KeyType)
93               $(LREF OriginalType)
94               $(LREF PropertyType)
95               $(LREF SymbolType)
96               $(LREF ValueType)
97     ))
98     $(TR $(TD Traits for removing type qualfiers) $(TD
99               $(LREF Unconst)
100               $(LREF Unshared)
101               $(LREF Unqualified)
102     ))
103     $(TR $(TD Type Constructors) $(TD
104               $(LREF ConstOf)
105               $(LREF ImmutableOf)
106               $(LREF InoutOf)
107               $(LREF SharedOf)
108     ))
109     $(TR $(TD Misc) $(TD
110               $(LREF defaultInit)
111               $(LREF EnumMembers)
112               $(LREF lvalueOf)
113               $(LREF rvalueOf)
114     ))
115     )
116 
117     Copyright: Copyright The D Language Foundation 2005 - 2024.
118     License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
119     Authors:   $(HTTP jmdavisprog.com, Jonathan M Davis)
120                $(HTTP digitalmars.com, Walter Bright),
121                Tomasz Stachowiak (`isExpressions`),
122                $(HTTP erdani.org, Andrei Alexandrescu),
123                Shin Fujishiro,
124                $(HTTP octarineparrot.com, Robert Clipsham),
125                $(HTTP klickverbot.at, David Nadlinger),
126                Kenji Hara,
127                Shoichi Kato
128     Source:    $(PHOBOSSRC phobos/sys/traits)
129 +/
130 module phobos.sys.traits;
131 
132 /++
133     Whether the given type is an "aggregate type" - i.e. a struct, class,
134     interface, or union. Enum types whose base type is an aggregate type are
135     also considered aggregate types.
136   +/
137 template isAggregateType(T)
138 {
139     static if (is(T == enum))
140         enum isAggregateType = isAggregateType!(OriginalType!T);
141     else
142         enum isAggregateType = is(T == struct) || is(T == class) || is(T == interface) || is(T == union);
143 }
144 
145 ///
146 @safe unittest
147 {
148     struct S {}
149     class C {}
150     interface I {}
151     union U {}
152 
153     static assert( isAggregateType!S);
154     static assert( isAggregateType!C);
155     static assert( isAggregateType!I);
156     static assert( isAggregateType!U);
157     static assert( isAggregateType!(const S));
158     static assert( isAggregateType!(shared C));
159 
160     static assert(!isAggregateType!int);
161     static assert(!isAggregateType!string);
162     static assert(!isAggregateType!(S*));
163     static assert(!isAggregateType!(C[]));
164     static assert(!isAggregateType!(I[string]));
165 
166     enum ES : S { a = S.init }
167     enum EC : C { a = C.init }
168     enum EI : I { a = I.init }
169     enum EU : U { a = U.init }
170 
171     static assert( isAggregateType!ES);
172     static assert( isAggregateType!EC);
173     static assert( isAggregateType!EI);
174     static assert( isAggregateType!EU);
175     static assert( isAggregateType!(const ES));
176     static assert( isAggregateType!(const EC));
177 }
178 
179 /++
180     Whether the given type is a dynamic array (or what is sometimes referred to
181     as a slice, since a dynamic array in D is a slice of memory).
182 
183     Note that this does not include implicit conversions or enum types. The
184     type itself must be a dynamic array.
185 
186     Remember that D's dynamic arrays are essentially:
187     ---
188     struct DynamicArray(T)
189     {
190         size_t length;
191         T* ptr;
192     }
193     ---
194     where $(D ptr) points to the first element in the array, and $(D length) is
195     the number of elements in the array.
196 
197     A dynamic array is not a pointer (unlike arrays in C/C++), and its elements
198     do not live inside the dynamic array itself. The dynamic array is simply a
199     slice of memory and does not own or manage its own memory. It can be a
200     slice of any piece of memory, including GC-allocated memory, the stack,
201     malloc-ed memory, etc. (with what kind of memory it is of course being
202     determined by how the dynamic array was created in the first place)
203     - though if you do any operations on it which end up requiring allocation
204     (e.g. appending to it if it doesn't have the capacity to expand in-place,
205     which it won't if it isn't a slice of GC-allocated memory), then that
206     reallocation will result in the dynamic array being a slice of newly
207     allocated, GC-backed memory (regardless of what it was a slice of before),
208     since it's the GC that deals with those allocations.
209 
210     As long as code just accesses the elements or members of the dynamic array
211     - or reduces its length so that it's a smaller slice - it will continue to
212     point to whatever block of memory it pointed to originally. And because the
213     GC makes sure that appending to a dynamic array does not stomp on the
214     memory of any other dynamic arrays, appending to a dynamic array will not
215     affect any other dynamic array which is a slice of that same block of
216     memory whether a reallocation occurs or not.
217 
218     Regardless, since what allocated the memory that the dynamic array is a
219     slice of is irrevelant to the type of the dynamic array, whether a given
220     type is a dynamic array has nothing to do with the kind of memory that's
221     backing it. A dynamic array which is a slice of a static array of $(D int)
222     is the the same type as a dynamic array of $(D int) allocated with $(D new)
223     - i.e. both are $(D int[]). So, this trait will not tell you anything about
224     what kind of memory a dynamic array is a slice of. It just tells you
225     whether the type is a dynamic array or not.
226 
227     If for some reason, it matters for a function what kind of memory backs one
228     of its parameters which is a dynamic array, or it needs to be made clear
229     whether the function will possibly cause that dynamic array to be
230     reallocated, then that needs to be indicated by the documentation and
231     cannot be enforced with a template constraint. A template constraint can
232     enforce that a type used with a template meets certain criteria (e.g. that
233     it's a dynamic array), but it cannot enforce anything about how the
234     template actually uses the type.
235 
236     However, it $(D is) possible to enforce that a function doesn't use any
237     operations on a dynamic array which might cause it to be reallocated by
238     marking that function as $(D @nogc).
239 
240     In most cases though, code can be written to not care what kind of memory
241     backs a dynamic array, because none of the operations on a dynamic array
242     actually care what kind of memory it's a slice of. It mostly just matters
243     when you need to track the lifetime of the memory, because it wasn't
244     allocated by the GC, or when it matters whether a dynamic array could be
245     reallocated or not (e.g. because the code needs to have that dynamic array
246     continue to point to the same block of memory).
247 
248     See_Also:
249         $(LREF isPointer)
250         $(LREF isStaticArray)
251         $(DDSUBLINK spec/arrays, , The language spec for arrays)
252   +/
253 enum isDynamicArray(T) = is(T == U[], U);
254 
255 ///
256 @safe unittest
257 {
258     // Some types which are dynamic arrays.
259     static assert( isDynamicArray!(int[]));
260     static assert( isDynamicArray!(const int[]));
261     static assert( isDynamicArray!(inout int[]));
262     static assert( isDynamicArray!(shared(int)[]));
263     static assert( isDynamicArray!string);
264 
265     static assert( isDynamicArray!(typeof([1, 2, 3])));
266     static assert( isDynamicArray!(typeof("dlang")));
267 
268     int[] arr;
269     static assert( isDynamicArray!(typeof(arr)));
270 
271     // Some types which aren't dynamic arrays.
272     static assert(!isDynamicArray!int);
273     static assert(!isDynamicArray!(int*));
274     static assert(!isDynamicArray!real);
275 
276     static struct S
277     {
278         int[] arr;
279     }
280     static assert(!isDynamicArray!S);
281 
282     // The struct itself isn't considered a dynamic array,
283     // but its member variable is when checked directly.
284     static assert( isDynamicArray!(typeof(S.arr)));
285 
286     // Static arrays.
287     static assert(!isDynamicArray!(int[5]));
288     static assert(!isDynamicArray!(const(int)[5]));
289 
290     int[2] sArr = [42, 97];
291     static assert(!isDynamicArray!(typeof(sArr)));
292 
293     // While a static array is not a dynamic array,
294     // a slice of a static array is a dynamic array.
295     static assert( isDynamicArray!(typeof(sArr[])));
296 
297     // Dynamic array of static arrays.
298     static assert( isDynamicArray!(long[3][]));
299 
300     // Static array of dynamic arrays.
301     static assert(!isDynamicArray!(long[][3]));
302 
303     // Associative array.
304     static assert(!isDynamicArray!(int[string]));
305 
306     // While typeof(null) gets treated as void[] in some contexts, it is
307     // distinct from void[] and is not considered to be a dynamic array.
308     static assert(!isDynamicArray!(typeof(null)));
309 
310     // However, naturally, if null is cast to a dynamic array, it's a
311     // dynamic array, since the cast forces the type.
312     static assert( isDynamicArray!(typeof(cast(int[]) null)));
313 
314     enum E : int[]
315     {
316         a = [1, 2, 3],
317     }
318 
319     // Enums do not count.
320     static assert(!isDynamicArray!E);
321 
322     static struct AliasThis
323     {
324         int[] arr;
325         alias this = arr;
326     }
327 
328     // Other implicit conversions do not count.
329     static assert(!isDynamicArray!AliasThis);
330 }
331 
332 @safe unittest
333 {
334     import phobos.sys.meta : Alias, AliasSeq;
335 
336     static struct AliasThis(T)
337     {
338         T member;
339         alias this = member;
340     }
341 
342     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
343     {
344         foreach (T; AliasSeq!(int[], char[], string, long[3][], double[string][]))
345         {
346             enum E : Q!T { a = Q!T.init }
347 
348             static assert( isDynamicArray!(Q!T));
349             static assert(!isDynamicArray!E);
350             static assert(!isDynamicArray!(AliasThis!(Q!T)));
351         }
352 
353         foreach (T; AliasSeq!(int, int[51], int[][2],
354                               char[][int][11], immutable char[13u],
355                               const(real)[1], const(real)[1][1], void[0]))
356         {
357             enum E : Q!T { a = Q!T.init }
358 
359             static assert(!isDynamicArray!(Q!T));
360             static assert(!isDynamicArray!E);
361             static assert(!isDynamicArray!(AliasThis!(Q!T)));
362         }
363     }
364 }
365 
366 /++
367     Whether type $(D T) is a static array.
368 
369     Note that this does not include implicit conversions or enum types. The
370     type itself must be a static array. This is in contrast to
371     $(D __traits(isStaticArray, T)) which is true for enums (but not for other
372     implict conversions to static arrays).
373 
374     As explained in the module documentation, traits like this one are not true
375     for enums (unlike most of the $(D __traits) traits) in order to avoid
376     testing for implicit conversions by default with template constraints,
377     since that tends to lead to subtle bugs when the code isn't carefully
378     written to take implicit conversions into account.
379 
380     See also:
381         $(DDSUBLINK spec/traits, isStaticArray, $(D __traits(isStaticArray, T)))
382         $(DDSUBLINK spec/arrays, , The language spec for arrays)
383   +/
384 enum isStaticArray(T) = is(T == U[n], U, size_t n);
385 
386 ///
387 @safe unittest
388 {
389     // Some types which are static arrays.
390     static assert( isStaticArray!(int[12]));
391     static assert( isStaticArray!(const int[42]));
392     static assert( isStaticArray!(inout int[0]));
393     static assert( isStaticArray!(shared(int)[907]));
394     static assert( isStaticArray!(immutable(char)[5]));
395 
396     // D doesn't have static array literals, but you get the same effect
397     // by casting a dynamic array literal to a static array, and of course,
398     // the result is typed as a static array.
399     static assert( isStaticArray!(typeof(cast(int[3]) [1, 2, 3])));
400 
401     int[2] sArr = [1, 2];
402     static assert( isStaticArray!(typeof(sArr)));
403 
404     // Some types which are not static arrays.
405     static assert(!isStaticArray!int);
406     static assert(!isStaticArray!(int*));
407     static assert(!isStaticArray!real);
408 
409     static struct S
410     {
411         int[4] arr;
412     }
413     static assert(!isStaticArray!S);
414 
415     // The struct itself isn't considered a static array,
416     // but its member variable is when checked directly.
417     static assert( isStaticArray!(typeof(S.arr)));
418 
419     // Dynamic arrays.
420     static assert(!isStaticArray!(int[]));
421     static assert(!isStaticArray!(const(int)[]));
422     static assert(!isStaticArray!string);
423 
424     int[] arr;
425     static assert(!isStaticArray!(typeof(arr)));
426 
427     // A slice of a static array is of course not a static array,
428     // because it's a dynamic array.
429     static assert(!isStaticArray!(typeof(sArr[])));
430 
431     // Static array of dynamic arrays.
432     static assert( isStaticArray!(long[][3]));
433 
434     // Dynamic array of static arrays.
435     static assert(!isStaticArray!(long[3][]));
436 
437     // Associative array.
438     static assert(!isStaticArray!(int[string]));
439 
440     // Of course, null is not considered to be a static array.
441     static assert(!isStaticArray!(typeof(null)));
442 
443     enum E : int[3]
444     {
445         a = [1, 2, 3],
446     }
447 
448     // Enums do not count.
449     static assert(!isStaticArray!E);
450 
451     // This is where isStaticArray differs from __traits(isStaticArray, ...)
452     static assert( __traits(isStaticArray, E));
453 
454     static struct AliasThis
455     {
456         int[] arr;
457         alias this = arr;
458     }
459 
460     // Other implicit conversions do not count.
461     static assert(!isStaticArray!AliasThis);
462 
463     static assert(!__traits(isStaticArray, AliasThis));
464 }
465 
466 @safe unittest
467 {
468     import phobos.sys.meta : Alias, AliasSeq;
469 
470     static struct AliasThis(T)
471     {
472         T member;
473         alias this = member;
474     }
475 
476     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
477     {
478         foreach (T; AliasSeq!(int[51], int[][2],
479                               char[][int][11], immutable char[13u],
480                               const(real)[1], const(real)[1][1], void[0]))
481         {
482             enum E : Q!T { a = Q!T.init, }
483 
484             static assert( isStaticArray!(Q!T));
485             static assert(!isStaticArray!E);
486             static assert(!isStaticArray!(AliasThis!(Q!T)));
487         }
488 
489         foreach (T; AliasSeq!(int, int[], char[], string, long[3][], double[string][]))
490         {
491             enum E : Q!T { a = Q!T.init, }
492 
493             static assert(!isStaticArray!(Q!T));
494             static assert(!isStaticArray!E);
495             static assert(!isStaticArray!(AliasThis!(Q!T)));
496         }
497     }
498 }
499 
500 /++
501     Whether the given type is one of the built-in integer types, ignoring all
502     qualifiers.
503 
504     $(TABLE
505         $(TR $(TH Integer Types))
506         $(TR $(TD byte))
507         $(TR $(TD ubyte))
508         $(TR $(TD short))
509         $(TR $(TD ushort))
510         $(TR $(TD int))
511         $(TR $(TD uint))
512         $(TR $(TD long))
513         $(TR $(TD ulong))
514     )
515 
516     Note that this does not include implicit conversions or enum types. The
517     type itself must be one of the built-in integer types.
518 
519     This trait does have some similarities with $(D __traits(isIntegral, T)),
520     but $(D isIntegral) accepts a $(I lot) more types than isInteger does.
521     isInteger is specifically for testing for the built-in integer types,
522     whereas $(D isIntegral) tests for a whole set of types that are vaguely
523     integer-like (including $(D bool), the three built-in character types, and
524     some of the vector types from core.simd). So, for most code, isInteger is
525     going to be more appropriate, but obviously, it depends on what the code is
526     trying to do.
527 
528     See also:
529         $(DDSUBLINK spec/traits, isIntegral, $(D __traits(isIntegral, T)))
530         $(LREF isFloatingPoint)
531         $(LREF isSignedInteger)
532         $(LREF isNumeric)
533         $(LREF isUnsignedInteger)
534   +/
535 enum isInteger(T) = is(immutable T == immutable byte) ||
536                     is(immutable T == immutable ubyte) ||
537                     is(immutable T == immutable short) ||
538                     is(immutable T == immutable ushort) ||
539                     is(immutable T == immutable int) ||
540                     is(immutable T == immutable uint) ||
541                     is(immutable T == immutable long) ||
542                     is(immutable T == immutable ulong);
543 
544 ///
545 @safe unittest
546 {
547     // Some types which are integer types.
548     static assert( isInteger!byte);
549     static assert( isInteger!ubyte);
550     static assert( isInteger!short);
551     static assert( isInteger!ushort);
552     static assert( isInteger!int);
553     static assert( isInteger!uint);
554     static assert( isInteger!long);
555     static assert( isInteger!ulong);
556 
557     static assert( isInteger!(const ubyte));
558     static assert( isInteger!(immutable short));
559     static assert( isInteger!(inout int));
560     static assert( isInteger!(shared uint));
561     static assert( isInteger!(const shared ulong));
562 
563     static assert( isInteger!(typeof(42)));
564     static assert( isInteger!(typeof(1234567890L)));
565 
566     int i;
567     static assert( isInteger!(typeof(i)));
568 
569     // Some types which aren't integer types.
570     static assert(!isInteger!bool);
571     static assert(!isInteger!char);
572     static assert(!isInteger!wchar);
573     static assert(!isInteger!dchar);
574     static assert(!isInteger!(int[]));
575     static assert(!isInteger!(ubyte[4]));
576     static assert(!isInteger!(int*));
577     static assert(!isInteger!double);
578     static assert(!isInteger!string);
579 
580     static struct S
581     {
582         int i;
583     }
584     static assert(!isInteger!S);
585 
586     // The struct itself isn't considered an integer,
587     // but its member variable is when checked directly.
588     static assert( isInteger!(typeof(S.i)));
589 
590     enum E : int
591     {
592         a = 42
593     }
594 
595     // Enums do not count.
596     static assert(!isInteger!E);
597 
598     static struct AliasThis
599     {
600         int i;
601         alias this = i;
602     }
603 
604     // Other implicit conversions do not count.
605     static assert(!isInteger!AliasThis);
606 }
607 
608 @safe unittest
609 {
610     import phobos.sys.meta : Alias, AliasSeq;
611 
612     static struct AliasThis(T)
613     {
614         T member;
615         alias this = member;
616     }
617 
618     // The actual core.simd types available vary from system to system, so we
619     // have to be a bit creative here. The reason that we're testing these types
620     // is because __traits(isIntegral, T) accepts them, but isInteger is not
621     // supposed to.
622     template SIMDTypes()
623     {
624         import core.simd;
625 
626         alias SIMDTypes = AliasSeq!();
627         static if (is(ubyte16))
628             SIMDTypes = AliasSeq!(SIMDTypes, ubyte16);
629         static if (is(int4))
630             SIMDTypes = AliasSeq!(SIMDTypes, int4);
631         static if (is(double2))
632             SIMDTypes = AliasSeq!(SIMDTypes, double2);
633         static if (is(void16))
634             SIMDTypes = AliasSeq!(SIMDTypes, void16);
635     }
636 
637     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
638     {
639         foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
640         {
641             enum E : Q!T { a = Q!T.init }
642 
643             static assert( isInteger!(Q!T));
644             static assert(!isInteger!E);
645             static assert(!isInteger!(AliasThis!(Q!T)));
646         }
647 
648         foreach (T; AliasSeq!(bool, char, wchar, dchar, float, double, real, SIMDTypes!(),
649                               int[], ubyte[8], dchar[], void[], long*))
650         {
651             enum E : Q!T { a = Q!T.init }
652 
653             static assert(!isInteger!(Q!T));
654             static assert(!isInteger!E);
655             static assert(!isInteger!(AliasThis!(Q!T)));
656         }
657     }
658 }
659 
660 /++
661     Whether the given type is one of the built-in signed integer types, ignoring
662     all qualifiers.
663 
664     $(TABLE
665         $(TR $(TH Signed Integer Types))
666         $(TR $(TD byte))
667         $(TR $(TD short))
668         $(TR $(TD int))
669         $(TR $(TD long))
670     )
671 
672     Note that this does not include implicit conversions or enum types. The
673     type itself must be one of the built-in signed integer types.
674 
675     See also:
676         $(LREF isFloatingPoint)
677         $(LREF isInteger)
678         $(LREF isNumeric)
679         $(LREF isUnsignedInteger)
680   +/
681 enum isSignedInteger(T) = is(immutable T == immutable byte) ||
682                           is(immutable T == immutable short) ||
683                           is(immutable T == immutable int) ||
684                           is(immutable T == immutable long);
685 
686 ///
687 @safe unittest
688 {
689     // Some types which are signed integer types.
690     static assert( isSignedInteger!byte);
691     static assert( isSignedInteger!short);
692     static assert( isSignedInteger!int);
693     static assert( isSignedInteger!long);
694 
695     static assert( isSignedInteger!(const byte));
696     static assert( isSignedInteger!(immutable short));
697     static assert( isSignedInteger!(inout int));
698     static assert( isSignedInteger!(shared int));
699     static assert( isSignedInteger!(const shared long));
700 
701     static assert( isSignedInteger!(typeof(42)));
702     static assert( isSignedInteger!(typeof(1234567890L)));
703 
704     int i;
705     static assert( isSignedInteger!(typeof(i)));
706 
707     // Some types which aren't signed integer types.
708     static assert(!isSignedInteger!ubyte);
709     static assert(!isSignedInteger!ushort);
710     static assert(!isSignedInteger!uint);
711     static assert(!isSignedInteger!ulong);
712 
713     static assert(!isSignedInteger!bool);
714     static assert(!isSignedInteger!char);
715     static assert(!isSignedInteger!wchar);
716     static assert(!isSignedInteger!dchar);
717     static assert(!isSignedInteger!(int[]));
718     static assert(!isSignedInteger!(ubyte[4]));
719     static assert(!isSignedInteger!(int*));
720     static assert(!isSignedInteger!double);
721     static assert(!isSignedInteger!string);
722 
723     static struct S
724     {
725         int i;
726     }
727     static assert(!isSignedInteger!S);
728 
729     // The struct itself isn't considered a signed integer,
730     // but its member variable is when checked directly.
731     static assert( isSignedInteger!(typeof(S.i)));
732 
733     enum E : int
734     {
735         a = 42
736     }
737 
738     // Enums do not count.
739     static assert(!isSignedInteger!E);
740 
741     static struct AliasThis
742     {
743         int i;
744         alias this = i;
745     }
746 
747     // Other implicit conversions do not count.
748     static assert(!isSignedInteger!AliasThis);
749 }
750 
751 @safe unittest
752 {
753     import phobos.sys.meta : Alias, AliasSeq;
754 
755     static struct AliasThis(T)
756     {
757         T member;
758         alias this = member;
759     }
760 
761     // The actual core.simd types available vary from system to system, so we
762     // have to be a bit creative here. The reason that we're testing these types
763     // is because __traits(isIntegral, T) accepts them, but isSignedInteger is
764     // not supposed to.
765     template SIMDTypes()
766     {
767         import core.simd;
768 
769         alias SIMDTypes = AliasSeq!();
770         static if (is(ubyte16))
771             SIMDTypes = AliasSeq!(SIMDTypes, ubyte16);
772         static if (is(int4))
773             SIMDTypes = AliasSeq!(SIMDTypes, int4);
774         static if (is(double2))
775             SIMDTypes = AliasSeq!(SIMDTypes, double2);
776         static if (is(void16))
777             SIMDTypes = AliasSeq!(SIMDTypes, void16);
778     }
779 
780     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
781     {
782         foreach (T; AliasSeq!(byte, short, int, long))
783         {
784             enum E : Q!T { a = Q!T.init }
785 
786             static assert( isSignedInteger!(Q!T));
787             static assert(!isSignedInteger!E);
788             static assert(!isSignedInteger!(AliasThis!(Q!T)));
789         }
790 
791         foreach (T; AliasSeq!(ubyte, ushort, uint, ulong,
792                               bool, char, wchar, dchar, float, double, real, SIMDTypes!(),
793                               int[], ubyte[8], dchar[], void[], long*))
794         {
795             enum E : Q!T { a = Q!T.init }
796 
797             static assert(!isSignedInteger!(Q!T));
798             static assert(!isSignedInteger!E);
799             static assert(!isSignedInteger!(AliasThis!(Q!T)));
800         }
801     }
802 }
803 
804 /++
805     Whether the given type is one of the built-in unsigned integer types,
806     ignoring all qualifiers.
807 
808     $(TABLE
809         $(TR $(TH Integer Types))
810         $(TR $(TD ubyte))
811         $(TR $(TD ushort))
812         $(TR $(TD uint))
813         $(TR $(TD ulong))
814     )
815 
816     Note that this does not include implicit conversions or enum types. The
817     type itself must be one of the built-in unsigned integer types.
818 
819     This trait does have some similarities with $(D __traits(isUnsigned, T)),
820     but $(D isUnsigned) accepts a $(I lot) more types than isUnsignedInteger
821     does. isUnsignedInteger is specifically for testing for the built-in
822     unsigned integer types, whereas $(D isUnsigned) tests for a whole set of
823     types that are unsigned and vaguely integer-like (including $(D bool), the
824     three built-in character types, and some of the vector types from
825     core.simd). So, for most code, isUnsignedInteger is going to be more
826     appropriate, but obviously, it depends on what the code is trying to do.
827 
828     See also:
829         $(DDSUBLINK spec/traits, isUnsigned, $(D __traits(isUnsigned, T)))
830         $(LREF isFloatingPoint)
831         $(LREF isInteger)
832         $(LREF isSignedInteger)
833         $(LREF isNumeric)
834   +/
835 enum isUnsignedInteger(T) = is(immutable T == immutable ubyte) ||
836                             is(immutable T == immutable ushort) ||
837                             is(immutable T == immutable uint) ||
838                             is(immutable T == immutable ulong);
839 
840 ///
841 @safe unittest
842 {
843     // Some types which are unsigned integer types.
844     static assert( isUnsignedInteger!ubyte);
845     static assert( isUnsignedInteger!ushort);
846     static assert( isUnsignedInteger!uint);
847     static assert( isUnsignedInteger!ulong);
848 
849     static assert( isUnsignedInteger!(const ubyte));
850     static assert( isUnsignedInteger!(immutable ushort));
851     static assert( isUnsignedInteger!(inout uint));
852     static assert( isUnsignedInteger!(shared uint));
853     static assert( isUnsignedInteger!(const shared ulong));
854 
855     static assert( isUnsignedInteger!(typeof(42u)));
856     static assert( isUnsignedInteger!(typeof(1234567890UL)));
857 
858     uint u;
859     static assert( isUnsignedInteger!(typeof(u)));
860 
861     // Some types which aren't unsigned integer types.
862     static assert(!isUnsignedInteger!byte);
863     static assert(!isUnsignedInteger!short);
864     static assert(!isUnsignedInteger!int);
865     static assert(!isUnsignedInteger!long);
866 
867     static assert(!isUnsignedInteger!bool);
868     static assert(!isUnsignedInteger!char);
869     static assert(!isUnsignedInteger!wchar);
870     static assert(!isUnsignedInteger!dchar);
871     static assert(!isUnsignedInteger!(int[]));
872     static assert(!isUnsignedInteger!(ubyte[4]));
873     static assert(!isUnsignedInteger!(int*));
874     static assert(!isUnsignedInteger!double);
875     static assert(!isUnsignedInteger!string);
876 
877     static struct S
878     {
879         uint u;
880     }
881     static assert(!isUnsignedInteger!S);
882 
883     // The struct itself isn't considered an unsigned integer,
884     // but its member variable is when checked directly.
885     static assert( isUnsignedInteger!(typeof(S.u)));
886 
887     enum E : uint
888     {
889         a = 42
890     }
891 
892     // Enums do not count.
893     static assert(!isUnsignedInteger!E);
894 
895     static struct AliasThis
896     {
897         uint u;
898         alias this = u;
899     }
900 
901     // Other implicit conversions do not count.
902     static assert(!isUnsignedInteger!AliasThis);
903 }
904 
905 @safe unittest
906 {
907     import phobos.sys.meta : Alias, AliasSeq;
908 
909     static struct AliasThis(T)
910     {
911         T member;
912         alias this = member;
913     }
914 
915     // The actual core.simd types available vary from system to system, so we
916     // have to be a bit creative here. The reason that we're testing these types
917     // is because __traits(isIntegral, T) and __traits(isUnsigned, T) accept
918     // them, but isUnsignedInteger is not supposed to.
919     template SIMDTypes()
920     {
921         import core.simd;
922 
923         alias SIMDTypes = AliasSeq!();
924         static if (is(ubyte16))
925             SIMDTypes = AliasSeq!(SIMDTypes, ubyte16);
926         static if (is(int4))
927             SIMDTypes = AliasSeq!(SIMDTypes, int4);
928         static if (is(double2))
929             SIMDTypes = AliasSeq!(SIMDTypes, double2);
930         static if (is(void16))
931             SIMDTypes = AliasSeq!(SIMDTypes, void16);
932     }
933 
934     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
935     {
936         foreach (T; AliasSeq!(ubyte, ushort, uint, ulong))
937         {
938             enum E : Q!T { a = Q!T.init }
939 
940             static assert( isUnsignedInteger!(Q!T));
941             static assert(!isUnsignedInteger!E);
942             static assert(!isUnsignedInteger!(AliasThis!(Q!T)));
943         }
944 
945         foreach (T; AliasSeq!(byte, short, int, long,
946                               bool, char, wchar, dchar, float, double, real, SIMDTypes!(),
947                               int[], ubyte[8], dchar[], void[], long*))
948         {
949             enum E : Q!T { a = Q!T.init }
950 
951             static assert(!isUnsignedInteger!(Q!T));
952             static assert(!isUnsignedInteger!E);
953             static assert(!isUnsignedInteger!(AliasThis!(Q!T)));
954         }
955     }
956 }
957 
958 /++
959     Whether the given type is one of the built-in floating-point types, ignoring
960     all qualifiers.
961 
962     $(TABLE
963         $(TR $(TH Floating-Point Types))
964         $(TR $(TD float))
965         $(TR $(TD double))
966         $(TR $(TD real))
967     )
968 
969     Note that this does not include implicit conversions or enum types. The
970     type itself must be one of the built-in floating-point types.
971 
972     This trait does have some similarities with $(D __traits(isFloating, T)),
973     but $(D isFloating) accepts more types than isFloatingPoint does.
974     isFloatingPoint is specifically for testing for the built-in floating-point
975     types, whereas $(D isFloating) tests for a whole set of types that are
976     vaguely float-like (including enums with a base type which is a
977     floating-point type and some of the vector types from core.simd). So, for
978     most code, isFloatingPoint is going to be more appropriate, but obviously,
979     it depends on what the code is trying to do.
980 
981     See also:
982         $(DDSUBLINK spec/traits, isFloating, $(D __traits(isFloating, T)))
983         $(LREF isInteger)
984         $(LREF isSignedInteger)
985         $(LREF isNumeric)
986         $(LREF isUnsignedInteger)
987   +/
988 enum isFloatingPoint(T) = is(immutable T == immutable float) ||
989                           is(immutable T == immutable double) ||
990                           is(immutable T == immutable real);
991 
992 ///
993 @safe unittest
994 {
995     // Some types which are floating-point types.
996     static assert( isFloatingPoint!float);
997     static assert( isFloatingPoint!double);
998     static assert( isFloatingPoint!real);
999 
1000     static assert( isFloatingPoint!(const float));
1001     static assert( isFloatingPoint!(immutable float));
1002     static assert( isFloatingPoint!(inout double));
1003     static assert( isFloatingPoint!(shared double));
1004     static assert( isFloatingPoint!(const shared real));
1005 
1006     static assert( isFloatingPoint!(typeof(42.0)));
1007     static assert( isFloatingPoint!(typeof(42f)));
1008     static assert( isFloatingPoint!(typeof(1e5)));
1009     static assert( isFloatingPoint!(typeof(97.4L)));
1010 
1011     double d;
1012     static assert( isFloatingPoint!(typeof(d)));
1013 
1014     // Some types which aren't floating-point types.
1015     static assert(!isFloatingPoint!bool);
1016     static assert(!isFloatingPoint!char);
1017     static assert(!isFloatingPoint!dchar);
1018     static assert(!isFloatingPoint!int);
1019     static assert(!isFloatingPoint!long);
1020     static assert(!isFloatingPoint!(float[]));
1021     static assert(!isFloatingPoint!(double[4]));
1022     static assert(!isFloatingPoint!(real*));
1023     static assert(!isFloatingPoint!string);
1024 
1025     static struct S
1026     {
1027         double d;
1028     }
1029     static assert(!isFloatingPoint!S);
1030 
1031     // The struct itself isn't considered a floating-point type,
1032     // but its member variable is when checked directly.
1033     static assert( isFloatingPoint!(typeof(S.d)));
1034 
1035     enum E : double
1036     {
1037         a = 12.34
1038     }
1039 
1040     // Enums do not count.
1041     static assert(!isFloatingPoint!E);
1042 
1043     static struct AliasThis
1044     {
1045         double d;
1046         alias this = d;
1047     }
1048 
1049     // Other implicit conversions do not count.
1050     static assert(!isFloatingPoint!AliasThis);
1051 }
1052 
1053 @safe unittest
1054 {
1055     import phobos.sys.meta : Alias, AliasSeq;
1056 
1057     static struct AliasThis(T)
1058     {
1059         T member;
1060         alias this = member;
1061     }
1062 
1063     // The actual core.simd types available vary from system to system, so we
1064     // have to be a bit creative here. The reason that we're testing these types
1065     // is because __traits(isFloating, T) accepts them, but isFloatingPoint is
1066     // not supposed to.
1067     template SIMDTypes()
1068     {
1069         import core.simd;
1070 
1071         alias SIMDTypes = AliasSeq!();
1072         static if (is(int4))
1073             SIMDTypes = AliasSeq!(SIMDTypes, int4);
1074         static if (is(double2))
1075             SIMDTypes = AliasSeq!(SIMDTypes, double2);
1076         static if (is(void16))
1077             SIMDTypes = AliasSeq!(SIMDTypes, void16);
1078     }
1079 
1080     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
1081     {
1082         foreach (T; AliasSeq!(float, double, real))
1083         {
1084             enum E : Q!T { a = Q!T.init }
1085 
1086             static assert( isFloatingPoint!(Q!T));
1087             static assert(!isFloatingPoint!E);
1088             static assert(!isFloatingPoint!(AliasThis!(Q!T)));
1089         }
1090 
1091         foreach (T; AliasSeq!(bool, char, wchar, dchar, byte, ubyte, short, ushort,
1092                               int, uint, long, ulong, SIMDTypes!(),
1093                               int[], float[8], real[], void[], double*))
1094         {
1095             enum E : Q!T { a = Q!T.init }
1096 
1097             static assert(!isFloatingPoint!(Q!T));
1098             static assert(!isFloatingPoint!E);
1099             static assert(!isFloatingPoint!(AliasThis!(Q!T)));
1100         }
1101     }
1102 }
1103 
1104 /++
1105     Whether the given type is one of the built-in numeric types, ignoring all
1106     qualifiers. It's equivalent to $(D isInteger!T || isFloatingPoint!T), but
1107     it only involves a single template instantation instead of two.
1108 
1109     $(TABLE
1110         $(TR $(TH Numeric Types))
1111         $(TR $(TD byte))
1112         $(TR $(TD ubyte))
1113         $(TR $(TD short))
1114         $(TR $(TD ushort))
1115         $(TR $(TD int))
1116         $(TR $(TD uint))
1117         $(TR $(TD long))
1118         $(TR $(TD ulong))
1119         $(TR $(TD float))
1120         $(TR $(TD double))
1121         $(TR $(TD real))
1122     )
1123 
1124     Note that this does not include implicit conversions or enum types. The
1125     type itself must be one of the built-in numeric types.
1126 
1127     See_Also:
1128         $(LREF isFloatingPoint)
1129         $(LREF isInteger)
1130         $(LREF isSignedInteger)
1131         $(LREF isUnsignedInteger)
1132   +/
1133 enum isNumeric(T) = is(immutable T == immutable byte) ||
1134                     is(immutable T == immutable ubyte) ||
1135                     is(immutable T == immutable short) ||
1136                     is(immutable T == immutable ushort) ||
1137                     is(immutable T == immutable int) ||
1138                     is(immutable T == immutable uint) ||
1139                     is(immutable T == immutable long) ||
1140                     is(immutable T == immutable ulong) ||
1141                     is(immutable T == immutable float) ||
1142                     is(immutable T == immutable double) ||
1143                     is(immutable T == immutable real);
1144 
1145 ///
1146 @safe unittest
1147 {
1148     // Some types which are numeric types.
1149     static assert( isNumeric!byte);
1150     static assert( isNumeric!ubyte);
1151     static assert( isNumeric!short);
1152     static assert( isNumeric!ushort);
1153     static assert( isNumeric!int);
1154     static assert( isNumeric!uint);
1155     static assert( isNumeric!long);
1156     static assert( isNumeric!ulong);
1157     static assert( isNumeric!float);
1158     static assert( isNumeric!double);
1159     static assert( isNumeric!real);
1160 
1161     static assert( isNumeric!(const short));
1162     static assert( isNumeric!(immutable int));
1163     static assert( isNumeric!(inout uint));
1164     static assert( isNumeric!(shared long));
1165     static assert( isNumeric!(const shared real));
1166 
1167     static assert( isNumeric!(typeof(42)));
1168     static assert( isNumeric!(typeof(1234657890L)));
1169     static assert( isNumeric!(typeof(42.0)));
1170     static assert( isNumeric!(typeof(42f)));
1171     static assert( isNumeric!(typeof(1e5)));
1172     static assert( isNumeric!(typeof(97.4L)));
1173 
1174     int i;
1175     static assert( isNumeric!(typeof(i)));
1176 
1177     // Some types which aren't numeric types.
1178     static assert(!isNumeric!bool);
1179     static assert(!isNumeric!char);
1180     static assert(!isNumeric!dchar);
1181     static assert(!isNumeric!(int[]));
1182     static assert(!isNumeric!(double[4]));
1183     static assert(!isNumeric!(real*));
1184     static assert(!isNumeric!string);
1185 
1186     static struct S
1187     {
1188         int i;
1189     }
1190     static assert(!isNumeric!S);
1191 
1192     // The struct itself isn't considered a numeric type,
1193     // but its member variable is when checked directly.
1194     static assert( isNumeric!(typeof(S.i)));
1195 
1196     enum E : int
1197     {
1198         a = 42
1199     }
1200 
1201     // Enums do not count.
1202     static assert(!isNumeric!E);
1203 
1204     static struct AliasThis
1205     {
1206         int i;
1207         alias this = i;
1208     }
1209 
1210     // Other implicit conversions do not count.
1211     static assert(!isNumeric!AliasThis);
1212 }
1213 
1214 @safe unittest
1215 {
1216     import phobos.sys.meta : Alias, AliasSeq;
1217 
1218     static struct AliasThis(T)
1219     {
1220         T member;
1221         alias this = member;
1222     }
1223 
1224     // The actual core.simd types available vary from system to system, so we
1225     // have to be a bit creative here. The reason that we're testing these types
1226     // is because __traits(isInteger, T) and __traits(isFloating, T) accept
1227     // them, but isNumeric is not supposed to.
1228     template SIMDTypes()
1229     {
1230         import core.simd;
1231 
1232         alias SIMDTypes = AliasSeq!();
1233         static if (is(int4))
1234             SIMDTypes = AliasSeq!(SIMDTypes, int4);
1235         static if (is(double2))
1236             SIMDTypes = AliasSeq!(SIMDTypes, double2);
1237         static if (is(void16))
1238             SIMDTypes = AliasSeq!(SIMDTypes, void16);
1239     }
1240 
1241     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
1242     {
1243         foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong, float, double, real))
1244         {
1245             enum E : Q!T { a = Q!T.init }
1246 
1247             static assert( isNumeric!(Q!T));
1248             static assert(!isNumeric!E);
1249             static assert(!isNumeric!(AliasThis!(Q!T)));
1250         }
1251 
1252         foreach (T; AliasSeq!(bool, char, wchar, dchar, SIMDTypes!(),
1253                               int[], float[8], real[], void[], double*))
1254         {
1255             enum E : Q!T { a = Q!T.init }
1256 
1257             static assert(!isNumeric!(Q!T));
1258             static assert(!isNumeric!E);
1259             static assert(!isNumeric!(AliasThis!(Q!T)));
1260         }
1261     }
1262 }
1263 
1264 /++
1265     Whether the given type is a pointer.
1266 
1267     Note that this does not include implicit conversions or enum types. The
1268     type itself must be a pointer.
1269 
1270     Also, remember that unlike C/C++, D's arrays are not pointers. Rather, a
1271     dynamic array in D is a slice of memory which has a member which is a
1272     pointer to its first element and another member which is the length of the
1273     array as $(D size_t). So, a dynamic array / slice has a $(D ptr) member
1274     which is a pointer, but the dynamic array itself is not a pointer.
1275 
1276     See_Also:
1277         $(LREF isDynamicArray)
1278   +/
1279 enum isPointer(T) = is(T == U*, U);
1280 
1281 ///
1282 @system unittest
1283 {
1284     // Some types which are pointers.
1285     static assert( isPointer!(bool*));
1286     static assert( isPointer!(int*));
1287     static assert( isPointer!(int**));
1288     static assert( isPointer!(real*));
1289     static assert( isPointer!(string*));
1290 
1291     static assert( isPointer!(const int*));
1292     static assert( isPointer!(immutable int*));
1293     static assert( isPointer!(inout int*));
1294     static assert( isPointer!(shared int*));
1295     static assert( isPointer!(const shared int*));
1296 
1297     static assert( isPointer!(typeof("foobar".ptr)));
1298 
1299     int* ptr;
1300     static assert( isPointer!(typeof(ptr)));
1301 
1302     int i;
1303     static assert( isPointer!(typeof(&i)));
1304 
1305     // Some types which aren't pointers.
1306     static assert(!isPointer!bool);
1307     static assert(!isPointer!int);
1308     static assert(!isPointer!dchar);
1309     static assert(!isPointer!(int[]));
1310     static assert(!isPointer!(double[4]));
1311     static assert(!isPointer!string);
1312 
1313     static struct S
1314     {
1315         int* ptr;
1316     }
1317     static assert(!isPointer!S);
1318 
1319     // The struct itself isn't considered a numeric type,
1320     // but its member variable is when checked directly.
1321     static assert( isPointer!(typeof(S.ptr)));
1322 
1323     enum E : immutable(char*)
1324     {
1325         a = "foobar".ptr
1326     }
1327 
1328     // Enums do not count.
1329     static assert(!isPointer!E);
1330 
1331     static struct AliasThis
1332     {
1333         int* ptr;
1334         alias this = ptr;
1335     }
1336 
1337     // Other implicit conversions do not count.
1338     static assert(!isPointer!AliasThis);
1339 }
1340 
1341 @safe unittest
1342 {
1343     import phobos.sys.meta : Alias, AliasSeq;
1344 
1345     static struct AliasThis(T)
1346     {
1347         T member;
1348         alias this = member;
1349     }
1350 
1351     static struct S
1352     {
1353         int i;
1354     }
1355 
1356     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
1357     {
1358         foreach (T; AliasSeq!(long*, S*, S**, S***, double[]*))
1359         {
1360             enum E : Q!T { a = Q!T.init }
1361 
1362             static assert( isPointer!(Q!T));
1363             static assert(!isPointer!E);
1364             static assert(!isPointer!(AliasThis!(Q!T)));
1365         }
1366 
1367         foreach (T; AliasSeq!(bool, char, wchar, dchar, byte, int, uint, long,
1368                               int[], float[8], real[], void[]))
1369         {
1370             enum E : Q!T { a = Q!T.init }
1371 
1372             static assert(!isPointer!(Q!T));
1373             static assert(!isPointer!E);
1374             static assert(!isPointer!(AliasThis!(Q!T)));
1375         }
1376     }
1377 }
1378 
1379 /++
1380     Evaluates to $(D true) if given a type and $(D false) for all other symbols.
1381 
1382     This is equivalent to $(D is(T)), but some people may find using a named
1383     trait to be clearer, and it can be used in conjunction with templates that
1384     take a template predicate (such as those in phobos.sys.meta), which can't
1385     be done with naked is expressions.
1386 
1387     See_Also:
1388         $(DDSUBLINK dlang.org/spec/expression.html, is-type, Spec on the related is expression)
1389   +/
1390 enum isType(T) = true;
1391 
1392 /// Ditto
1393 enum isType(alias sym) = false;
1394 
1395 ///
1396 @safe unittest
1397 {
1398     static assert( isType!int);
1399     static assert( isType!(int[]));
1400     static assert( isType!string);
1401     static assert( isType!(int[int]));
1402     static assert( isType!(ubyte*));
1403     static assert( isType!void);
1404 
1405     int i;
1406     static assert(!isType!i);
1407     static assert( isType!(typeof(i)));
1408 
1409     struct S {}
1410     static assert( isType!S);
1411     static assert(!isType!(S.init));
1412 
1413     class C {}
1414     static assert( isType!C);
1415     static assert(!isType!(C.init));
1416 
1417     interface I {}
1418     static assert( isType!I);
1419     static assert(!isType!(I.init));
1420 
1421     union U {}
1422     static assert( isType!U);
1423     static assert(!isType!(U.init));
1424 
1425     static void func() {}
1426     static assert(!isType!func);
1427     static assert( isType!(typeof(func)));
1428 
1429     void funcWithContext() { ++i; }
1430     static assert(!isType!funcWithContext);
1431     static assert( isType!(typeof(funcWithContext)));
1432 
1433     int function() funcPtr;
1434     static assert(!isType!funcPtr);
1435     static assert( isType!(typeof(funcPtr)));
1436 
1437     int delegate() del;
1438     static assert(!isType!del);
1439     static assert( isType!(typeof(del)));
1440 
1441     template Templ() {}
1442     static assert(!isType!Templ);
1443     static assert(!isType!(Templ!()));
1444 
1445     template TemplWithType()
1446     {
1447         struct S {}
1448     }
1449     static assert(!isType!TemplWithType);
1450     static assert(!isType!(TemplWithType!()));
1451     static assert( isType!(TemplWithType!().S));
1452 
1453     struct TemplType() {}
1454     static assert(!isType!TemplType);
1455     static assert( isType!(TemplType!()));
1456 }
1457 
1458 /++
1459     Evaluates to $(D true) if the given type or symbol is an instantiation of
1460     the given template.
1461 
1462     The overload which takes $(D T) operates on types and indicates whether an
1463     aggregate type (i.e. struct, class, interface, or union) is an
1464     instantiation of the given template.
1465 
1466     The overload which takes $(D Symbol) operates on function templates,
1467     because unlike with aggregate types, the type of a function does not retain
1468     the fact that it was instantiated from a template. So, for functions, it's
1469     necessary to pass the function itself as a symbol rather than pass the type
1470     of the function.
1471 
1472     The overload which takes $(D Symbol) also works with templates which are
1473     not types or functions.
1474 
1475     The single-argument overload makes it so that it can be partially
1476     instantiated with the first argument, which will often be necessary with
1477     template predicates.
1478   +/
1479 template isInstantiationOf(alias Template, T)
1480 if (__traits(isTemplate, Template))
1481 {
1482     enum isInstantiationOf = is(T == Template!Args, Args...);
1483 }
1484 
1485 /++ Ditto +/
1486 template isInstantiationOf(alias Template, alias Symbol)
1487 if (__traits(isTemplate, Template))
1488 {
1489     enum impl(alias T : Template!Args, Args...) = true;
1490     enum impl(alias T) = false;
1491     enum isInstantiationOf = impl!Symbol;
1492 }
1493 
1494 /++ Ditto +/
1495 template isInstantiationOf(alias Template)
1496 if (__traits(isTemplate, Template))
1497 {
1498     enum isInstantiationOf(T) = is(T == Template!Args, Args...);
1499 
1500     template isInstantiationOf(alias Symbol)
1501     {
1502         enum impl(alias T : Template!Args, Args...) = true;
1503         enum impl(alias T) = false;
1504         enum isInstantiationOf = impl!Symbol;
1505     }
1506 }
1507 
1508 /// Examples of templated types.
1509 @safe unittest
1510 {
1511     static struct S(T) {}
1512     static class C(T) {}
1513 
1514     static assert( isInstantiationOf!(S, S!int));
1515     static assert( isInstantiationOf!(S, S!int));
1516     static assert( isInstantiationOf!(S, S!string));
1517     static assert( isInstantiationOf!(S, const S!string));
1518     static assert( isInstantiationOf!(S, shared S!string));
1519     static assert(!isInstantiationOf!(S, int));
1520     static assert(!isInstantiationOf!(S, C!int));
1521     static assert(!isInstantiationOf!(S, C!string));
1522     static assert(!isInstantiationOf!(S, C!(S!int)));
1523 
1524     static assert( isInstantiationOf!(C, C!int));
1525     static assert( isInstantiationOf!(C, C!string));
1526     static assert( isInstantiationOf!(C, const C!string));
1527     static assert( isInstantiationOf!(C, shared C!string));
1528     static assert(!isInstantiationOf!(C, int));
1529     static assert(!isInstantiationOf!(C, S!int));
1530     static assert(!isInstantiationOf!(C, S!string));
1531     static assert(!isInstantiationOf!(C, S!(C!int)));
1532 
1533     static struct Variadic(T...) {}
1534 
1535     static assert( isInstantiationOf!(Variadic, Variadic!()));
1536     static assert( isInstantiationOf!(Variadic, Variadic!int));
1537     static assert( isInstantiationOf!(Variadic, Variadic!(int, string)));
1538     static assert( isInstantiationOf!(Variadic, Variadic!(int, string, int)));
1539     static assert( isInstantiationOf!(Variadic, const Variadic!(int, short)));
1540     static assert( isInstantiationOf!(Variadic, shared Variadic!(int, short)));
1541     static assert(!isInstantiationOf!(Variadic, int));
1542     static assert(!isInstantiationOf!(Variadic, S!int));
1543     static assert(!isInstantiationOf!(Variadic, C!int));
1544 
1545     static struct ValueArg(int i) {}
1546     static assert( isInstantiationOf!(ValueArg, ValueArg!42));
1547     static assert( isInstantiationOf!(ValueArg, ValueArg!256));
1548     static assert( isInstantiationOf!(ValueArg, const ValueArg!1024));
1549     static assert( isInstantiationOf!(ValueArg, shared ValueArg!1024));
1550     static assert(!isInstantiationOf!(ValueArg, int));
1551     static assert(!isInstantiationOf!(ValueArg, S!int));
1552 
1553     int i;
1554 
1555     static struct AliasArg(alias Symbol) {}
1556     static assert( isInstantiationOf!(AliasArg, AliasArg!42));
1557     static assert( isInstantiationOf!(AliasArg, AliasArg!int));
1558     static assert( isInstantiationOf!(AliasArg, AliasArg!i));
1559     static assert( isInstantiationOf!(AliasArg, const AliasArg!i));
1560     static assert( isInstantiationOf!(AliasArg, shared AliasArg!i));
1561     static assert(!isInstantiationOf!(AliasArg, int));
1562     static assert(!isInstantiationOf!(AliasArg, S!int));
1563 
1564     // An uninstantiated template is not an instance of any template,
1565     // not even itself.
1566     static assert(!isInstantiationOf!(S, S));
1567     static assert(!isInstantiationOf!(S, C));
1568     static assert(!isInstantiationOf!(C, C));
1569     static assert(!isInstantiationOf!(C, S));
1570 
1571     // Variables of a templated type are not considered instantiations of that
1572     // type. For templated types, the overload which takes a type must be used.
1573     S!int s;
1574     C!string c;
1575     static assert(!isInstantiationOf!(S, s));
1576     static assert(!isInstantiationOf!(C, c));
1577 }
1578 
1579 // Examples of templated functions.
1580 @safe unittest
1581 {
1582     static int foo(T...)() { return 42; }
1583     static void bar(T...)(T var) {}
1584     static void baz(T)(T var) {}
1585     static bool frobozz(alias pred)(int) { return true; }
1586 
1587     static assert( isInstantiationOf!(foo, foo!int));
1588     static assert( isInstantiationOf!(foo, foo!string));
1589     static assert( isInstantiationOf!(foo, foo!(int, string)));
1590     static assert(!isInstantiationOf!(foo, bar!int));
1591     static assert(!isInstantiationOf!(foo, bar!string));
1592     static assert(!isInstantiationOf!(foo, bar!(int, string)));
1593 
1594     static assert( isInstantiationOf!(bar, bar!int));
1595     static assert( isInstantiationOf!(bar, bar!string));
1596     static assert( isInstantiationOf!(bar, bar!(int, string)));
1597     static assert(!isInstantiationOf!(bar, foo!int));
1598     static assert(!isInstantiationOf!(bar, foo!string));
1599     static assert(!isInstantiationOf!(bar, foo!(int, string)));
1600 
1601     static assert( isInstantiationOf!(baz, baz!int));
1602     static assert( isInstantiationOf!(baz, baz!string));
1603     static assert(!isInstantiationOf!(baz, foo!(int, string)));
1604 
1605     static assert( isInstantiationOf!(frobozz, frobozz!(a => a)));
1606     static assert( isInstantiationOf!(frobozz, frobozz!(a => a > 2)));
1607     static assert(!isInstantiationOf!(frobozz, baz!int));
1608 
1609     // Unfortunately, the function type is not considered an instantiation of
1610     // the template, because that information is not part of the type, unlike
1611     // with templated structs or classes.
1612     static assert(!isInstantiationOf!(foo, typeof(foo!int)));
1613     static assert(!isInstantiationOf!(bar, typeof(bar!int)));
1614 }
1615 
1616 // Examples of templates which aren't types or functions.
1617 @safe unittest
1618 {
1619     template SingleArg(T) {}
1620     template Variadic(T...) {}
1621     template ValueArg(string s) {}
1622     template Alias(alias symbol) {}
1623 
1624     static assert( isInstantiationOf!(SingleArg, SingleArg!int));
1625     static assert( isInstantiationOf!(SingleArg, SingleArg!string));
1626     static assert(!isInstantiationOf!(SingleArg, int));
1627     static assert(!isInstantiationOf!(SingleArg, Variadic!int));
1628 
1629     static assert( isInstantiationOf!(Variadic, Variadic!()));
1630     static assert( isInstantiationOf!(Variadic, Variadic!int));
1631     static assert( isInstantiationOf!(Variadic, Variadic!string));
1632     static assert( isInstantiationOf!(Variadic, Variadic!(short, int, long)));
1633     static assert(!isInstantiationOf!(Variadic, int));
1634     static assert(!isInstantiationOf!(Variadic, SingleArg!int));
1635 
1636     static assert( isInstantiationOf!(ValueArg, ValueArg!"dlang"));
1637     static assert( isInstantiationOf!(ValueArg, ValueArg!"foobar"));
1638     static assert(!isInstantiationOf!(ValueArg, string));
1639     static assert(!isInstantiationOf!(ValueArg, Variadic!string));
1640 
1641     int i;
1642 
1643     static assert( isInstantiationOf!(Alias, Alias!int));
1644     static assert( isInstantiationOf!(Alias, Alias!42));
1645     static assert( isInstantiationOf!(Alias, Alias!i));
1646     static assert(!isInstantiationOf!(Alias, int));
1647     static assert(!isInstantiationOf!(Alias, SingleArg!int));
1648 }
1649 
1650 /// Examples of partial instantation.
1651 @safe unittest
1652 {
1653     static struct SingleArg(T) {}
1654     static struct Variadic(T...) {}
1655 
1656     alias isSingleArg = isInstantiationOf!SingleArg;
1657     alias isVariadic = isInstantiationOf!Variadic;
1658 
1659     static assert( isSingleArg!(SingleArg!int));
1660     static assert( isSingleArg!(const SingleArg!int));
1661     static assert(!isSingleArg!int);
1662     static assert(!isSingleArg!(Variadic!int));
1663 
1664     static assert( isVariadic!(Variadic!()));
1665     static assert( isVariadic!(Variadic!int));
1666     static assert( isVariadic!(shared Variadic!int));
1667     static assert( isVariadic!(Variadic!(int, string)));
1668     static assert(!isVariadic!int);
1669     static assert(!isVariadic!(SingleArg!int));
1670 
1671     T foo(T)(T t) { return t; }
1672     T likeFoo(T)(T t) { return t; }
1673     bool bar(alias pred)(int i) { return pred(i); }
1674 
1675     alias isFoo = isInstantiationOf!foo;
1676     alias isBar = isInstantiationOf!bar;
1677 
1678     static assert( isFoo!(foo!int));
1679     static assert( isFoo!(foo!string));
1680     static assert(!isFoo!int);
1681     static assert(!isFoo!(likeFoo!int));
1682     static assert(!isFoo!(bar!(a => true)));
1683 
1684     static assert( isBar!(bar!(a => true)));
1685     static assert( isBar!(bar!(a => a > 2)));
1686     static assert(!isBar!int);
1687     static assert(!isBar!(foo!int));
1688     static assert(!isBar!(likeFoo!int));
1689 }
1690 
1691 /++
1692     Evaluates to the default-initialized value of the given type.
1693 
1694     defaultInit should be used in generic code in contexts where the
1695     default-initialized value of a type is needed rather than that type's
1696     $(D init) value.
1697 
1698     For most types, the default-initialized value of a type $(I is) its
1699     $(D init) value - i.e. for some type, $(D T), it would normally be
1700     $(D T.init). However, there are some corner cases in the language where a
1701     type's $(D init) value is not its default-initialized value. In particular,
1702 
1703     1. If a type is a non-$(K_STATIC) nested struct, it has a context pointer
1704        which refers to the scope in which it's declared. So, its
1705        default-initialized value is its $(D init) value $(I plus) the value for
1706        its context pointer. However, if such a nested struct is explicitly
1707        initialized with just its $(D init) value instead of being
1708        default-initialized or being constructed via a constructor, then its
1709        context pointer is $(K_NULL), potentially leading to segfaults when the
1710        object is used.
1711     2. If a type is a struct for which default initialization has been disabled
1712        using $(D @disable this();), then while its $(D init) value is still used
1713        as the value of the object at the start of a constructor call (as is the
1714        case with any struct), the struct cannot be default-initialized and must
1715        instead be explicitly constructed. So, instead of $(D T.init) being the
1716        default-initialized value, it's just the struct's initial state before
1717        the constructor constructs the object, and the struct does not actually
1718        have a default-initialized value.
1719 
1720     In the case of #2, there is no default initialization for the struct,
1721     whereas in the case of #1, there $(I is) default initialization for the
1722     struct but only within the scope where the struct is declared. Outside of
1723     that scope, the compiler does not have access to that scope and therefore
1724     cannot iniitialize the context pointer with a value, so a compilation error
1725     results. And so, either case can make it so that a struct cannot be
1726     default-initialized.
1727 
1728     In both cases, an instance of the struct can still be explicitly
1729     initialized with its $(D init) value, but that will usually lead to
1730     incorrect code, because either the object's context pointer will be
1731     $(K_NULL), or it's a type which was designed with the idea that it would
1732     only ever be explicitly constructed. So, while sometimes it's still
1733     appropriate to explicitly use the $(D init) value (e.g. by default,
1734     $(REF1 destroy, object) will set the object to its $(D init) value after
1735     destroying it so that it's in a valid state to have its destructor called
1736     afterwards in cases where the object is still going to be destroyed when it
1737     leaves scope), in general, generic code which needs to explicitly
1738     default-initialize a variable shouldn't use the type's $(D init) value.
1739 
1740     For a type, $(D T), which is a struct which does not declare a $(K_STATIC)
1741     $(D opCall), $(D T()) can be used instead of $(D T.init) to get the type's
1742     default-initialized value, and unlike $(D T.init), it will fail to compile
1743     if the object cannot actually be default-initialized (be it because it has
1744     disabled default initialization, or because it's a nested struct outside of
1745     the scope where that struct was declared). So, unlike $(D T.init), it
1746     won't compile in cases where default initialization does not work, and thus
1747     it can't accidentally be used to initialize a struct which cannot be
1748     default-intiialized. Also, for nested structs, $(D T()) will initialize the
1749     context pointer, unlike $(D T.init). So, using $(D T()) normally gives the
1750     actual default-initialized value for the type or fails to compile if the
1751     type cannot be default-initialized.
1752 
1753     However, unfortunately, using $(D T()) does not work in generic code,
1754     because it is legal for a struct to declare a $(K_STATIC) $(D opCall) which
1755     takes no arguments, overriding the normal behavior of $(D T()) and making
1756     it so that it's no longer the default-initialized value. Instead, it's
1757     whatever $(K_STATIC) $(D opCall) returns, and $(K_STATIC) $(D opCall) can
1758     return any type, not just $(D T), because even though it looks like a
1759     constructor call, it's not actually a constructor call, and it can return
1760     whatever the programmer felt like - including $(K_VOID). This means that
1761     the only way to consistently get a default-initialized value for a type in
1762     generic code is to actually declare a variable and not give it a value.
1763 
1764     So, in order to work around that, defaultInit does that for you.
1765     $(D defaultInit!Foo) evaluates to the default-initialized value of $(D Foo),
1766     but unlike $(D Foo.init), it won't compile when $(D Foo) cannot be
1767     default-initialized. And it won't get hijacked by $(K_STATIC) $(D opCall).
1768 
1769     The downside to using such a helper template is that it will not work with
1770     a nested struct even within the scope where that nested struct is declared
1771     (since defaultInit is declared outside of that scope). So, code which needs
1772     to get a default-initialized instance of a nested struct within the scope
1773     where it's declared will either have to simply declare a variable and not
1774     initialize it or use $(D T()) to explicitly get the default-initialized
1775     value. And since this is within the code where the type is declared, it's
1776     fully within the programmer's control to not declare a $(K_STATIC)
1777     $(D opCall) for it. So, it shouldn't be a problem in practice.
1778   +/
1779 template defaultInit(T)
1780 if (is(typeof({T t;})))
1781 {
1782     // At present, simply using T.init should work, since all of the cases where
1783     // it wouldn't won't get past the template constraint. However, it's
1784     // possible that that will change at some point in the future, and this
1785     // approach is guaranteed to give whatever the default-initialized value is
1786     // regardless of whether it's T.init.
1787     enum defaultInit = (){ T retval; return retval; }();
1788 }
1789 
1790 ///
1791 @safe unittest
1792 {
1793     static assert(defaultInit!int == 0);
1794     static assert(defaultInit!bool == false);
1795     static assert(defaultInit!(int*) is null);
1796     static assert(defaultInit!(int[]) is null);
1797     static assert(defaultInit!string is null);
1798     static assert(defaultInit!(int[2]) == [0, 0]);
1799 
1800     static struct S
1801     {
1802         int i = 42;
1803     }
1804     static assert(defaultInit!S == S(42));
1805 
1806     static assert(defaultInit!Object is null);
1807 
1808     interface I
1809     {
1810         bool foo();
1811     }
1812     static assert(defaultInit!I is null);
1813 
1814     static struct NoDefaultInit
1815     {
1816         int i;
1817         @disable this();
1818     }
1819 
1820     // It's not legal to default-initialize NoDefaultInit, because it has
1821     // disabled default initialization.
1822     static assert(!__traits(compiles, defaultInit!NoDefaultInit));
1823 
1824     int var = 2;
1825     struct Nested
1826     {
1827         int i = 40;
1828 
1829         int foo()
1830         {
1831             return i + var;
1832         }
1833     }
1834 
1835     // defaultInit doesn't have access to this scope and thus cannot
1836     // initialize the nested struct.
1837     static assert(!__traits(compiles, defaultInit!Nested));
1838 
1839     // However, because Nested has no static opCall (and we know it doesn't
1840     // because we're doing this in the same scope where Nested was declared),
1841     // Nested() can be used to get the default-initialized value.
1842     static assert(Nested() == Nested(40));
1843 
1844     Nested nested;
1845     assert(Nested() == nested);
1846 
1847     // Both have properly initialized context pointers,
1848     // whereas Nested.init does not.
1849     assert(Nested().foo() == nested.foo());
1850 
1851     // defaultInit does not get hijacked by static opCall.
1852     static struct HasOpCall
1853     {
1854         int i;
1855 
1856         static opCall()
1857         {
1858             return HasOpCall(42);
1859         }
1860 
1861         static opCall(int i)
1862         {
1863             HasOpCall retval;
1864             retval.i = i;
1865             return retval;
1866         }
1867     }
1868 
1869     static assert(defaultInit!HasOpCall == HasOpCall(0));
1870     static assert(HasOpCall() == HasOpCall(42));
1871 }
1872 
1873 @safe unittest
1874 {
1875     static struct NoCopy
1876     {
1877         int i = 17;
1878         @disable this(this);
1879     }
1880     static assert(defaultInit!NoCopy == NoCopy(17));
1881 
1882     string function() funcPtr;
1883     static assert(defaultInit!(SymbolType!funcPtr) is null);
1884 
1885     string delegate() del;
1886     static assert(defaultInit!(SymbolType!del) is null);
1887 
1888     int function() @property propFuncPtr;
1889     static assert(defaultInit!(SymbolType!propFuncPtr) is null);
1890 
1891     int delegate() @property propDel;
1892     static assert(defaultInit!(SymbolType!propDel) is null);
1893 }
1894 
1895 /++
1896     Evaluates to an $(D AliasSeq) containing the members of an enum type.
1897 
1898     The elements of the $(D AliasSeq) are in the same order as they are in the
1899     enum declaration.
1900 
1901     An enum can have multiple members with the same value, so if code needs the
1902     enum values to be unique (e.g. if it's generating a switch statement from
1903     them), then $(REF Unique, phobos, sys, meta) can be used to filter out the
1904     duplicate values - e.g. $(D Unique!(isEqual, EnumMembers!E)).
1905   +/
1906 template EnumMembers(E)
1907 if (is(E == enum))
1908 {
1909     import phobos.sys.meta : AliasSeq;
1910 
1911     alias EnumMembers = AliasSeq!();
1912     static foreach (member; __traits(allMembers, E))
1913         EnumMembers = AliasSeq!(EnumMembers, __traits(getMember, E, member));
1914 }
1915 
1916 /// Create an array of enum values.
1917 @safe unittest
1918 {
1919     enum Sqrts : real
1920     {
1921         one = 1,
1922         two = 1.41421,
1923         three = 1.73205
1924     }
1925     auto sqrts = [EnumMembers!Sqrts];
1926     assert(sqrts == [Sqrts.one, Sqrts.two, Sqrts.three]);
1927 }
1928 
1929 /++
1930     A generic function $(D rank(v)) in the following example uses this template
1931     for finding a member $(D e) in an enum type $(D E).
1932  +/
1933 @safe unittest
1934 {
1935     // Returns i if e is the i-th member of E.
1936     static size_t rank(E)(E e)
1937     if (is(E == enum))
1938     {
1939         static foreach (i, member; EnumMembers!E)
1940         {
1941             if (e == member)
1942                 return i;
1943         }
1944         assert(0, "Not an enum member");
1945     }
1946 
1947     enum Mode
1948     {
1949         read = 1,
1950         write = 2,
1951         map = 4
1952     }
1953     assert(rank(Mode.read) == 0);
1954     assert(rank(Mode.write) == 1);
1955     assert(rank(Mode.map) == 2);
1956 }
1957 
1958 /// Use EnumMembers to generate a switch statement using static foreach.
1959 @safe unittest
1960 {
1961     static class Foo
1962     {
1963         string calledMethod;
1964         void foo() @safe { calledMethod = "foo"; }
1965         void bar() @safe { calledMethod = "bar"; }
1966         void baz() @safe { calledMethod = "baz"; }
1967     }
1968 
1969     enum FuncName : string { foo = "foo", bar = "bar", baz = "baz" }
1970 
1971     auto foo = new Foo;
1972 
1973     s: final switch (FuncName.bar)
1974     {
1975         static foreach (member; EnumMembers!FuncName)
1976         {
1977             // Generate a case for each enum value.
1978             case member:
1979             {
1980                 // Call foo.{enum value}().
1981                 __traits(getMember, foo, member)();
1982                 break s;
1983             }
1984         }
1985     }
1986 
1987     // Since we passed FuncName.bar to the switch statement, the bar member
1988     // function was called.
1989     assert(foo.calledMethod == "bar");
1990 }
1991 
1992 @safe unittest
1993 {
1994     {
1995         enum A { a }
1996         static assert([EnumMembers!A] == [A.a]);
1997         enum B { a, b, c, d, e }
1998         static assert([EnumMembers!B] == [B.a, B.b, B.c, B.d, B.e]);
1999     }
2000     {
2001         enum A : string { a = "alpha", b = "beta" }
2002         static assert([EnumMembers!A] == [A.a, A.b]);
2003 
2004         static struct S
2005         {
2006             int value;
2007             int opCmp(S rhs) const nothrow { return value - rhs.value; }
2008         }
2009         enum B : S { a = S(1), b = S(2), c = S(3) }
2010         static assert([EnumMembers!B] == [B.a, B.b, B.c]);
2011     }
2012     {
2013         enum A { a = 0, b = 0, c = 1, d = 1, e }
2014         static assert([EnumMembers!A] == [A.a, A.b, A.c, A.d, A.e]);
2015     }
2016     {
2017         enum E { member, a = 0, b = 0 }
2018 
2019         static assert(__traits(isSame, EnumMembers!E[0], E.member));
2020         static assert(__traits(isSame, EnumMembers!E[1], E.a));
2021         static assert(__traits(isSame, EnumMembers!E[2], E.b));
2022 
2023         static assert(__traits(identifier, EnumMembers!E[0]) == "member");
2024         static assert(__traits(identifier, EnumMembers!E[1]) == "a");
2025         static assert(__traits(identifier, EnumMembers!E[2]) == "b");
2026     }
2027 }
2028 
2029 // https://issues.dlang.org/show_bug.cgi?id=14561: huge enums
2030 @safe unittest
2031 {
2032     static string genEnum()
2033     {
2034         string result = "enum TLAs {";
2035         foreach (c0; '0' .. '2' + 1)
2036         {
2037             foreach (c1; '0' .. '9' + 1)
2038             {
2039                 foreach (c2; '0' .. '9' + 1)
2040                 {
2041                     foreach (c3; '0' .. '9' + 1)
2042                     {
2043                         result ~= '_';
2044                         result ~= c0;
2045                         result ~= c1;
2046                         result ~= c2;
2047                         result ~= c3;
2048                         result ~= ',';
2049                     }
2050                 }
2051             }
2052         }
2053         result ~= '}';
2054         return result;
2055     }
2056     mixin(genEnum);
2057     static assert(EnumMembers!TLAs[0] == TLAs._0000);
2058     static assert(EnumMembers!TLAs[$ - 1] == TLAs._2999);
2059 }
2060 
2061 /++
2062     Whether the type $(D From) is implicitly convertible to the type $(D To).
2063 
2064     Note that template constraints should be very careful about when they test
2065     for implicit conversions and in general should prefer to either test for an
2066     exact set of types or for types which compile with a particular piece of
2067     code rather than being designed to accept any type which implicitly converts
2068     to a particular type.
2069 
2070     This is because having a type pass a template constraint based on an
2071     implicit conversion but then not have the implicit conversion actually take
2072     place (which it won't unless the template does something to force it
2073     internally) can lead to either compilation errors or subtle behavioral
2074     differences - and even when the conversion is done explicitly within a
2075     templated function, since it's not done at the call site, it can still lead
2076     to subtle bugs in some cases (e.g. if slicing a static array is involved).
2077 
2078     For situations where code needs to verify that a type is implicitly
2079     convertible based solely on its qualifiers, $(LREF isQualifierConvertible)
2080     would be a more appropriate choice than isImplicitlyConvertible.
2081 
2082     Given how trivial the $(D is) expression for isImplicitlyConvertible is -
2083     $(D is(To : From)) - this trait is provided primarily so that it can be
2084     used in conjunction with templates that use a template predicate (such as
2085     many of the templates in phobos.sys.meta).
2086 
2087     The single-argument overload makes it so that it can be partially
2088     instantiated with the first argument, which will often be necessary with
2089     template predicates.
2090 
2091     See_Also:
2092         $(DDSUBLINK dlang.org/spec/type, implicit-conversions, Spec on implicit conversions)
2093         $(DDSUBLINK spec/const3, implicit_qualifier_conversions, Spec for implicit qualifier conversions)
2094         $(LREF isQualifierConvertible)
2095   +/
2096 enum isImplicitlyConvertible(From, To) = is(From : To);
2097 
2098 /++ Ditto +/
2099 template isImplicitlyConvertible(From)
2100 {
2101     enum isImplicitlyConvertible(To) = is(From : To);
2102 }
2103 
2104 ///
2105 @safe unittest
2106 {
2107     static assert( isImplicitlyConvertible!(byte, long));
2108     static assert( isImplicitlyConvertible!(ushort, long));
2109     static assert( isImplicitlyConvertible!(int, long));
2110     static assert( isImplicitlyConvertible!(long, long));
2111     static assert( isImplicitlyConvertible!(ulong, long));
2112 
2113     static assert( isImplicitlyConvertible!(ubyte, int));
2114     static assert( isImplicitlyConvertible!(short, int));
2115     static assert( isImplicitlyConvertible!(int, int));
2116     static assert( isImplicitlyConvertible!(uint, int));
2117     static assert(!isImplicitlyConvertible!(long, int));
2118     static assert(!isImplicitlyConvertible!(ulong, int));
2119 
2120     static assert(!isImplicitlyConvertible!(int, string));
2121     static assert(!isImplicitlyConvertible!(int, int[]));
2122     static assert(!isImplicitlyConvertible!(int, int*));
2123 
2124     static assert(!isImplicitlyConvertible!(string, int));
2125     static assert(!isImplicitlyConvertible!(int[], int));
2126     static assert(!isImplicitlyConvertible!(int*, int));
2127 
2128     // For better or worse, bool and the built-in character types will
2129     // implicitly convert to integer or floating-point types if the target type
2130     // is large enough. Sometimes, this is desirable, whereas at other times,
2131     // it can have very surprising results, so it's one reason why code should
2132     // be very careful when testing for implicit conversions.
2133     static assert( isImplicitlyConvertible!(bool, int));
2134     static assert( isImplicitlyConvertible!(char, int));
2135     static assert( isImplicitlyConvertible!(wchar, int));
2136     static assert( isImplicitlyConvertible!(dchar, int));
2137 
2138     static assert( isImplicitlyConvertible!(bool, ubyte));
2139     static assert( isImplicitlyConvertible!(char, ubyte));
2140     static assert(!isImplicitlyConvertible!(wchar, ubyte));
2141     static assert(!isImplicitlyConvertible!(dchar, ubyte));
2142 
2143     static assert( isImplicitlyConvertible!(bool, double));
2144     static assert( isImplicitlyConvertible!(char, double));
2145     static assert( isImplicitlyConvertible!(wchar, double));
2146     static assert( isImplicitlyConvertible!(dchar, double));
2147 
2148     // Value types can be implicitly converted regardless of their qualifiers
2149     // thanks to the fact that they're copied.
2150     static assert( isImplicitlyConvertible!(int, int));
2151     static assert( isImplicitlyConvertible!(const int, int));
2152     static assert( isImplicitlyConvertible!(immutable int, int));
2153     static assert( isImplicitlyConvertible!(inout int, int));
2154 
2155     static assert( isImplicitlyConvertible!(int, const int));
2156     static assert( isImplicitlyConvertible!(int, immutable int));
2157     static assert( isImplicitlyConvertible!(int, inout int));
2158 
2159     // Reference types are far more restrictive about which implicit conversions
2160     // they allow, because qualifiers in D are transitive.
2161     static assert( isImplicitlyConvertible!(int*, int*));
2162     static assert(!isImplicitlyConvertible!(const int*, int*));
2163     static assert(!isImplicitlyConvertible!(immutable int*, int*));
2164 
2165     static assert( isImplicitlyConvertible!(int*, const int*));
2166     static assert( isImplicitlyConvertible!(const int*, const int*));
2167     static assert( isImplicitlyConvertible!(immutable int*, const int*));
2168 
2169     static assert(!isImplicitlyConvertible!(int*, immutable int*));
2170     static assert(!isImplicitlyConvertible!(const int*, immutable int*));
2171     static assert( isImplicitlyConvertible!(immutable int*, immutable int*));
2172 
2173     // Note that inout gets a bit weird, since it's only used with function
2174     // parameters, and it's a stand-in for whatever mutability qualifiers the
2175     // type actually has. So, a function parameter that's inout accepts any
2176     // mutability, but you can't actually implicitly convert to inout, because
2177     // it's unknown within the function what the actual mutability of the type
2178     // is. It will differ depending on the function arguments of a specific
2179     // call to that function, so the same code has to work with all combinations
2180     // of mutability qualifiers.
2181     static assert(!isImplicitlyConvertible!(int*, inout int*));
2182     static assert(!isImplicitlyConvertible!(const int*, inout int*));
2183     static assert(!isImplicitlyConvertible!(immutable int*, inout int*));
2184     static assert( isImplicitlyConvertible!(inout int*, inout int*));
2185 
2186     static assert(!isImplicitlyConvertible!(inout int*, int*));
2187     static assert( isImplicitlyConvertible!(inout int*, const int*));
2188     static assert(!isImplicitlyConvertible!(inout int*, immutable int*));
2189 
2190     // Enums implicitly convert to their base type.
2191     enum E : int
2192     {
2193         a = 42
2194     }
2195     static assert( isImplicitlyConvertible!(E, int));
2196     static assert( isImplicitlyConvertible!(E, long));
2197     static assert(!isImplicitlyConvertible!(E, int[]));
2198 
2199     // Structs only implicit convert to another type via declaring an
2200     // alias this.
2201     static struct S
2202     {
2203         int i;
2204     }
2205     static assert(!isImplicitlyConvertible!(S, int));
2206     static assert(!isImplicitlyConvertible!(S, long));
2207     static assert(!isImplicitlyConvertible!(S, string));
2208 
2209     static struct AliasThis
2210     {
2211         int i;
2212         alias this = i;
2213     }
2214     static assert( isImplicitlyConvertible!(AliasThis, int));
2215     static assert( isImplicitlyConvertible!(AliasThis, long));
2216     static assert(!isImplicitlyConvertible!(AliasThis, string));
2217 
2218     static struct AliasThis2
2219     {
2220         AliasThis at;
2221         alias this = at;
2222     }
2223     static assert( isImplicitlyConvertible!(AliasThis2, AliasThis));
2224     static assert( isImplicitlyConvertible!(AliasThis2, int));
2225     static assert( isImplicitlyConvertible!(AliasThis2, long));
2226     static assert(!isImplicitlyConvertible!(AliasThis2, string));
2227 
2228     static struct AliasThis3
2229     {
2230         AliasThis2 at;
2231         alias this = at;
2232     }
2233     static assert( isImplicitlyConvertible!(AliasThis3, AliasThis2));
2234     static assert( isImplicitlyConvertible!(AliasThis3, AliasThis));
2235     static assert( isImplicitlyConvertible!(AliasThis3, int));
2236     static assert( isImplicitlyConvertible!(AliasThis3, long));
2237     static assert(!isImplicitlyConvertible!(AliasThis3, string));
2238 
2239     // D does not support implicit conversions via construction.
2240     static struct Cons
2241     {
2242         this(int i)
2243         {
2244             this.i = i;
2245         }
2246 
2247         int i;
2248     }
2249     static assert(!isImplicitlyConvertible!(int, Cons));
2250 
2251     // Classes support implicit conversion based on their class and
2252     // interface hierarchies.
2253     static interface I1 {}
2254     static class Base : I1 {}
2255 
2256     static interface I2 {}
2257     static class Foo : Base, I2 {}
2258 
2259     static class Bar : Base {}
2260 
2261     static assert( isImplicitlyConvertible!(Base, Base));
2262     static assert(!isImplicitlyConvertible!(Base, Foo));
2263     static assert(!isImplicitlyConvertible!(Base, Bar));
2264     static assert( isImplicitlyConvertible!(Base, I1));
2265     static assert(!isImplicitlyConvertible!(Base, I2));
2266 
2267     static assert( isImplicitlyConvertible!(Foo, Base));
2268     static assert( isImplicitlyConvertible!(Foo, Foo));
2269     static assert(!isImplicitlyConvertible!(Foo, Bar));
2270     static assert( isImplicitlyConvertible!(Foo, I1));
2271     static assert( isImplicitlyConvertible!(Foo, I2));
2272 
2273     static assert( isImplicitlyConvertible!(Bar, Base));
2274     static assert(!isImplicitlyConvertible!(Bar, Foo));
2275     static assert( isImplicitlyConvertible!(Bar, Bar));
2276     static assert( isImplicitlyConvertible!(Bar, I1));
2277     static assert(!isImplicitlyConvertible!(Bar, I2));
2278 
2279     static assert(!isImplicitlyConvertible!(I1, Base));
2280     static assert(!isImplicitlyConvertible!(I1, Foo));
2281     static assert(!isImplicitlyConvertible!(I1, Bar));
2282     static assert( isImplicitlyConvertible!(I1, I1));
2283     static assert(!isImplicitlyConvertible!(I1, I2));
2284 
2285     static assert(!isImplicitlyConvertible!(I2, Base));
2286     static assert(!isImplicitlyConvertible!(I2, Foo));
2287     static assert(!isImplicitlyConvertible!(I2, Bar));
2288     static assert(!isImplicitlyConvertible!(I2, I1));
2289     static assert( isImplicitlyConvertible!(I2, I2));
2290 
2291     // Note that arrays are not implicitly convertible even when their elements
2292     // are implicitly convertible.
2293     static assert(!isImplicitlyConvertible!(ubyte[], uint[]));
2294     static assert(!isImplicitlyConvertible!(Foo[], Base[]));
2295     static assert(!isImplicitlyConvertible!(Bar[], Base[]));
2296 
2297     // However, like with pointers, dynamic arrays are convertible based on
2298     // constness.
2299     static assert( isImplicitlyConvertible!(Base[], const Base[]));
2300     static assert( isImplicitlyConvertible!(Base[], const(Base)[]));
2301     static assert(!isImplicitlyConvertible!(Base[], immutable(Base)[]));
2302     static assert(!isImplicitlyConvertible!(const Base[], immutable Base[]));
2303     static assert( isImplicitlyConvertible!(const Base[], const Base[]));
2304     static assert(!isImplicitlyConvertible!(const Base[], immutable Base[]));
2305 }
2306 
2307 /++
2308     isImplicitlyConvertible can be used with partial instantiation so that it
2309     can be passed to a template which takes a unary predicate.
2310   +/
2311 @safe unittest
2312 {
2313     import phobos.sys.meta : AliasSeq, all, indexOf;
2314 
2315     // byte is implicitly convertible to byte, short, int, and long.
2316     static assert(all!(isImplicitlyConvertible!byte, short, int, long));
2317 
2318     // const(char)[] at index 2 is the first type in the AliasSeq which string
2319     // can be implicitly converted to.
2320     alias Types = AliasSeq!(int, char[], const(char)[], string, int*);
2321     static assert(indexOf!(isImplicitlyConvertible!string, Types) == 2);
2322 }
2323 
2324 /++
2325     Whether $(D From) is
2326     $(DDSUBLINK spec/const3, implicit_qualifier_conversions, qualifier-convertible)
2327     to $(D To).
2328 
2329     This is testing whether $(D From) and $(D To) are the same type - minus the
2330     qualifiers - and whether the qualifiers on $(D From) can be implicitly
2331     converted to the qualifiers on $(D To). No other implicit conversions are
2332     taken into account.
2333 
2334     For instance, $(D const int*) is not implicitly convertible to $(D int*),
2335     because that would violate $(D const). That means that $(D const) is not
2336     qualifier convertible to mutable. And as such, $(I any) $(D const) type
2337     is not qualifier convertible to a mutable type even if it's implicitly
2338     convertible. E.G. $(D const int) is implicitly convertible to $(D int),
2339     because it can be copied to avoid violating $(D const), but it's still not
2340     qualifier convertible, because $(D const) types in general cannot be
2341     implicitly converted to mutable.
2342 
2343     The exact types being tested matter, because they need to be the same
2344     (minus the qualifiers) in order to be considered convertible, but beyond
2345     that, all that matters for the conversion is whether those qualifers would
2346     be convertible regardless of which types they were on. So, if you're having
2347     trouble picturing whether $(D From) would be qualifier convertible to
2348     $(D To), then consider which conversions would be allowed from $(D From[])
2349     to $(D To[]) (and remember that dynamic arrays are only implicitly
2350     convertible based on their qualifers).
2351 
2352     The $(DDSUBLINK spec/const3, implicit_qualifier_conversions, spec) provides
2353     a table of which qualifiers can be implcitly converted to which other
2354     qualifers (and of course, there a bunch of examples below).
2355 
2356     So, isQualifierConvertible can be used in a case like
2357     $(D isQualifierConvertible!(ReturnType!(typeof(foo(bar))), const char),
2358     which would be testing that the return type of $(D foo(bar)) was $(D char),
2359     $(D const char), or $(D immutable char) (since those are the only types
2360     which are qualifier convertible to $(D const char)).
2361 
2362     This is in contrast to
2363     $(D isImplicitlyConvertible!(ReturnType!(typeof(foo(bar))), const char),
2364     which would be $(D true) for $(I any) type which was implicitly convertible
2365     to $(D const char) rather than just $(D char), $(D const char), and
2366     $(D immutable char).
2367 
2368     The single-argument overload makes it so that it can be partially
2369     instantiated with the first argument, which will often be necessary with
2370     template predicates.
2371 
2372     See_Also:
2373         $(DDSUBLINK spec/const3, implicit_qualifier_conversions, Spec for implicit qualifier conversions)
2374         $(LREF isImplicitlyConvertible)
2375   +/
2376 enum isQualifierConvertible(From, To) = is(immutable From == immutable To) && is(From* : To*);
2377 
2378 /++ Ditto +/
2379 template isQualifierConvertible(From)
2380 {
2381     enum isQualifierConvertible(To) =  is(immutable From == immutable To) && is(From* : To*);
2382 }
2383 
2384 ///
2385 @safe unittest
2386 {
2387     // i.e. char* -> const char*
2388     static assert( isQualifierConvertible!(char, const char));
2389 
2390     // i.e. const char* -> char*
2391     static assert(!isQualifierConvertible!(const char, char));
2392 
2393     static assert( isQualifierConvertible!(int, int));
2394     static assert( isQualifierConvertible!(int, const int));
2395     static assert(!isQualifierConvertible!(int, immutable int));
2396 
2397     static assert(!isQualifierConvertible!(const int, int));
2398     static assert( isQualifierConvertible!(const int, const int));
2399     static assert(!isQualifierConvertible!(const int, immutable int));
2400 
2401     static assert(!isQualifierConvertible!(immutable int, int));
2402     static assert( isQualifierConvertible!(immutable int, const int));
2403     static assert( isQualifierConvertible!(immutable int, immutable int));
2404 
2405     // Note that inout gets a bit weird, since it's only used with function
2406     // parameters, and it's a stand-in for whatever mutability qualifiers the
2407     // type actually has. So, a function parameter that's inout accepts any
2408     // mutability, but you can't actually implicitly convert to inout, because
2409     // it's unknown within the function what the actual mutability of the type
2410     // is. It will differ depending on the function arguments of a specific
2411     // call to that function, so the same code has to work with all combinations
2412     // of mutability qualifiers.
2413     static assert(!isQualifierConvertible!(int, inout int));
2414     static assert(!isQualifierConvertible!(const int, inout int));
2415     static assert(!isQualifierConvertible!(immutable int, inout int));
2416     static assert( isQualifierConvertible!(inout int, inout int));
2417 
2418     static assert(!isQualifierConvertible!(inout int, int));
2419     static assert( isQualifierConvertible!(inout int, const int));
2420     static assert(!isQualifierConvertible!(inout int, immutable int));
2421 
2422     // shared is of course also a qualifier.
2423     static assert(!isQualifierConvertible!(int, shared int));
2424     static assert(!isQualifierConvertible!(int, const shared int));
2425     static assert(!isQualifierConvertible!(const int, shared int));
2426     static assert(!isQualifierConvertible!(const int, const shared int));
2427     static assert(!isQualifierConvertible!(immutable int, shared int));
2428     static assert( isQualifierConvertible!(immutable int, const shared int));
2429 
2430     static assert(!isQualifierConvertible!(shared int, int));
2431     static assert(!isQualifierConvertible!(shared int, const int));
2432     static assert(!isQualifierConvertible!(shared int, immutable int));
2433     static assert( isQualifierConvertible!(shared int, shared int));
2434     static assert( isQualifierConvertible!(shared int, const shared int));
2435 
2436     static assert(!isQualifierConvertible!(const shared int, int));
2437     static assert(!isQualifierConvertible!(const shared int, const int));
2438     static assert(!isQualifierConvertible!(const shared int, immutable int));
2439     static assert(!isQualifierConvertible!(const shared int, shared int));
2440     static assert( isQualifierConvertible!(const shared int, const shared int));
2441 
2442     // Implicit conversions don't count unless they're based purely on
2443     // qualifiers.
2444     enum E : int
2445     {
2446         a = 1
2447     }
2448 
2449     static assert(!isQualifierConvertible!(E, int));
2450     static assert(!isQualifierConvertible!(E, const int));
2451     static assert( isQualifierConvertible!(E, E));
2452     static assert( isQualifierConvertible!(E, const E));
2453     static assert(!isQualifierConvertible!(E, immutable E));
2454 
2455     static struct AliasThis
2456     {
2457         int i;
2458         alias this = i;
2459     }
2460 
2461     static assert(!isQualifierConvertible!(AliasThis, int));
2462     static assert(!isQualifierConvertible!(AliasThis, const int));
2463     static assert( isQualifierConvertible!(AliasThis, AliasThis));
2464     static assert( isQualifierConvertible!(AliasThis, const AliasThis));
2465     static assert(!isQualifierConvertible!(AliasThis, immutable AliasThis));
2466 
2467     // The qualifiers are irrelevant if the types aren't the same when
2468     // stripped of all qualifers.
2469     static assert(!isQualifierConvertible!(int, long));
2470     static assert(!isQualifierConvertible!(int, const long));
2471     static assert(!isQualifierConvertible!(string, const(ubyte)[]));
2472 }
2473 
2474 /++
2475     isQualifierConvertible can be used with partial instantiation so that it
2476     can be passed to a template which takes a unary predicate.
2477   +/
2478 @safe unittest
2479 {
2480     import phobos.sys.meta : AliasSeq, all, indexOf;
2481 
2482     // byte is qualifier convertible to byte and const byte.
2483     static assert(all!(isQualifierConvertible!byte, byte, const byte));
2484 
2485     // const(char[]) at index 2 is the first type in the AliasSeq which string
2486     // is qualifier convertible to.
2487     alias Types = AliasSeq!(int, char[], const(char[]), string, int*);
2488     static assert(indexOf!(isQualifierConvertible!string, Types) == 2);
2489 }
2490 
2491 @safe unittest
2492 {
2493     import phobos.sys.meta : AliasSeq;
2494 
2495     alias Types = AliasSeq!(int, const int, shared int, inout int, const shared int,
2496                             const inout int, inout shared int, const inout shared int, immutable int);
2497 
2498     // https://dlang.org/spec/const3.html#implicit_qualifier_conversions
2499     enum _ = 0;
2500     static immutable bool[Types.length][Types.length] conversions = [
2501     //   m   c   s   i   cs  ci  is  cis im
2502         [1,  1,  _,  _,  _,  _,  _,  _,  _],  // mutable
2503         [_,  1,  _,  _,  _,  _,  _,  _,  _],  // const
2504         [_,  _,  1,  _,  1,  _,  _,  _,  _],  // shared
2505         [_,  1,  _,  1,  _,  1,  _,  _,  _],  // inout
2506         [_,  _,  _,  _,  1,  _,  _,  _,  _],  // const shared
2507         [_,  1,  _,  _,  _,  1,  _,  _,  _],  // const inout
2508         [_,  _,  _,  _,  1,  _,  1,  1,  _],  // inout shared
2509         [_,  _,  _,  _,  1,  _,  _,  1,  _],  // const inout shared
2510         [_,  1,  _,  _,  1,  1,  _,  1,  1],  // immutable
2511     ];
2512 
2513     foreach (i, From; Types)
2514     {
2515         foreach (j, To; Types)
2516         {
2517             static assert(isQualifierConvertible!(From, To) == conversions[i][j],
2518                           "`isQualifierConvertible!(" ~ From.stringof ~ ", " ~ To.stringof ~ ")`" ~
2519                           " should be `" ~ (conversions[i][j] ? "true`" : "false`"));
2520         }
2521     }
2522 }
2523 
2524 /++
2525     Whether the given values are equal per $(D ==).
2526 
2527     All this does is $(D lhs == rhs) but in an eponymous template, so most code
2528     shouldn't use it. It's intended to be used in conjunction with templates
2529     that take a template predicate - such as those in phobos.sys.meta.
2530 
2531     The single-argument overload makes it so that it can be partially
2532     instantiated with the first argument, which will often be necessary with
2533     template predicates.
2534 
2535     Note that in most cases, even when comparing values at compile time, using
2536     isEqual makes no sense, because you can use CTFE to just compare two values
2537     (or expressions which evaluate to values), but in rare cases where you need
2538     to compare symbols in an $(D AliasSeq) by value with a template predicate
2539     while still leaving them as symbols in an $(D AliasSeq), then isEqual would
2540     be needed.
2541 
2542     A prime example of this would be $(D Unique!(isEqual, EnumMembers!MyEnum)),
2543     which results in an $(D AliasSeq) containing the list of members of
2544     $(D MyEnum) but without any duplicate values (e.g. to use when doing code
2545     generation to create a final switch).
2546 
2547     Alternatively, code such as $(D [EnumMembers!MyEnum].sort().unique()) could
2548     be used to get a dynamic array of the enum members with no duplicate values
2549     via CTFE, thus avoiding the need for template predicates or anything from
2550     phobos.sys.meta. However, you then have a dynamic array of enum values
2551     rather than an $(D AliasSeq) of symbols for those enum members, which
2552     affects what you can do with type introspection. So, which approach is
2553     better depends on what the code needs to do with the enum members.
2554 
2555     In general, however, if code doesn't need an $(D AliasSeq), and an array of
2556     values will do the trick, then it's more efficient to operate on an array of
2557     values with CTFE and avoid using isEqual or other templates to operate on
2558     the values as an $(D AliasSeq).
2559 
2560     See_Also:
2561         $(LREF isSameSymbol)
2562         $(LREF isSameType)
2563   +/
2564 enum isEqual(alias lhs, alias rhs) = lhs == rhs;
2565 
2566 /++ Ditto +/
2567 template isEqual(alias lhs)
2568 {
2569     enum isEqual(alias rhs) = lhs == rhs;
2570 }
2571 
2572 /// It acts just like ==, but it's a template.
2573 @safe unittest
2574 {
2575     enum a = 42;
2576 
2577     static assert( isEqual!(a, 42));
2578     static assert( isEqual!(20, 10 + 10));
2579 
2580     static assert(!isEqual!(a, 120));
2581     static assert(!isEqual!(77, 19 * 7 + 2));
2582 
2583     // b cannot be read at compile time, so it won't work with isEqual.
2584     int b = 99;
2585     static assert(!__traits(compiles, isEqual!(b, 99)));
2586 }
2587 
2588 /++
2589     Comparing some of the differences between an $(D AliasSeq) of enum members
2590     and an array of enum values created from an $(D AliasSeq) of enum members.
2591   +/
2592 @safe unittest
2593 {
2594     import phobos.sys.meta : AliasSeq, Unique;
2595 
2596     enum E
2597     {
2598         a = 0,
2599         b = 22,
2600         c = 33,
2601         d = 0,
2602         e = 256,
2603         f = 33,
2604         g = 7
2605     }
2606 
2607     alias uniqueMembers = Unique!(isEqual, EnumMembers!E);
2608     static assert(uniqueMembers.length == 5);
2609 
2610     static assert(__traits(isSame, uniqueMembers[0], E.a));
2611     static assert(__traits(isSame, uniqueMembers[1], E.b));
2612     static assert(__traits(isSame, uniqueMembers[2], E.c));
2613     static assert(__traits(isSame, uniqueMembers[3], E.e));
2614     static assert(__traits(isSame, uniqueMembers[4], E.g));
2615 
2616     static assert(__traits(identifier, uniqueMembers[0]) == "a");
2617     static assert(__traits(identifier, uniqueMembers[1]) == "b");
2618     static assert(__traits(identifier, uniqueMembers[2]) == "c");
2619     static assert(__traits(identifier, uniqueMembers[3]) == "e");
2620     static assert(__traits(identifier, uniqueMembers[4]) == "g");
2621 
2622     // Same value but different symbol.
2623     static assert(uniqueMembers[0] == E.d);
2624     static assert(!__traits(isSame, uniqueMembers[0], E.d));
2625 
2626     // is expressions compare types, not symbols or values, and these AliasSeqs
2627     // contain the list of symbols for the enum members, not types, so the is
2628     // expression evaluates to false even though the symbols are the same.
2629     static assert(!is(uniqueMembers == AliasSeq!(E.a, E.b, E.c, E.e, E.g)));
2630 
2631     // Once the members are converted to an array, the types are the same, and
2632     // the values are the same, but the symbols are not the same. Instead of
2633     // being the symbols E.a, E.b, etc., they're just values with the type E
2634     // which match the values of E.a, E.b, etc.
2635     enum arr = [uniqueMembers];
2636     static assert(is(typeof(arr) == E[]));
2637 
2638     static assert(arr == [E.a, E.b, E.c, E.e, E.g]);
2639     static assert(arr == [E.d, E.b, E.f, E.e, E.g]);
2640 
2641     static assert(!__traits(isSame, arr[0], E.a));
2642     static assert(!__traits(isSame, arr[1], E.b));
2643     static assert(!__traits(isSame, arr[2], E.c));
2644     static assert(!__traits(isSame, arr[3], E.e));
2645     static assert(!__traits(isSame, arr[4], E.g));
2646 
2647     // Since arr[0] is just a value of type E, it's no longer the symbol, E.a,
2648     // even though its type is E, and its value is the same as that of E.a. And
2649     // unlike the actual members of an enum, an element of an array does not
2650     // have an identifier, so __traits(identifier, ...) doesn't work with it.
2651     static assert(!__traits(compiles, __traits(identifier, arr[0])));
2652 
2653     // Similarly, once an enum member from the AliasSeq is assigned to a
2654     // variable, __traits(identifer, ...) operates on the variable, not the
2655     // symbol from the AliasSeq or the value of the variable.
2656     auto var = uniqueMembers[0];
2657     static assert(__traits(identifier, var) == "var");
2658 
2659     // The same with a manifest constant.
2660     enum constant = uniqueMembers[0];
2661     static assert(__traits(identifier, constant) == "constant");
2662 }
2663 
2664 /++
2665     Whether the given symbols are the same symbol.
2666 
2667     All this does is $(D __traits(isSame, lhs, rhs)), so most code shouldn't
2668     use it. It's intended to be used in conjunction with templates that take a
2669     template predicate - such as those in phobos.sys.meta.
2670 
2671     The single-argument overload makes it so that it can be partially
2672     instantiated with the first argument, which will often be necessary with
2673     template predicates.
2674 
2675     See_Also:
2676         $(DDSUBLINK spec/traits, isSame, $(D __traits(isSame, lhs, rhs)))
2677         $(LREF isEqual)
2678         $(LREF isSameType)
2679   +/
2680 enum isSameSymbol(alias lhs, alias rhs) = __traits(isSame, lhs, rhs);
2681 
2682 /++ Ditto +/
2683 template isSameSymbol(alias lhs)
2684 {
2685     enum isSameSymbol(alias rhs) = __traits(isSame, lhs, rhs);
2686 }
2687 
2688 ///
2689 @safe unittest
2690 {
2691     int i;
2692     int j;
2693     real r;
2694 
2695     static assert( isSameSymbol!(i, i));
2696     static assert(!isSameSymbol!(i, j));
2697     static assert(!isSameSymbol!(i, r));
2698 
2699     static assert(!isSameSymbol!(j, i));
2700     static assert( isSameSymbol!(j, j));
2701     static assert(!isSameSymbol!(j, r));
2702 
2703     static assert(!isSameSymbol!(r, i));
2704     static assert(!isSameSymbol!(r, j));
2705     static assert( isSameSymbol!(r, r));
2706 
2707     auto foo() { return 0; }
2708     auto bar() { return 0; }
2709 
2710     static assert( isSameSymbol!(foo, foo));
2711     static assert(!isSameSymbol!(foo, bar));
2712     static assert(!isSameSymbol!(foo, i));
2713 
2714     static assert(!isSameSymbol!(bar, foo));
2715     static assert( isSameSymbol!(bar, bar));
2716     static assert(!isSameSymbol!(bar, i));
2717 
2718     // Types are symbols too. However, in most cases, they should be compared
2719     // as types, not symbols (be it with is expressions or with isSameType),
2720     // because the results aren't consistent between scalar types and
2721     // user-defined types with regards to type qualifiers when they're compared
2722     // as symbols.
2723     static assert( isSameSymbol!(double, double));
2724     static assert(!isSameSymbol!(double, const double));
2725     static assert(!isSameSymbol!(double, int));
2726     static assert( isSameSymbol!(Object, Object));
2727     static assert( isSameSymbol!(Object, const Object));
2728 
2729     static assert(!isSameSymbol!(i, int));
2730     static assert( isSameSymbol!(typeof(i), int));
2731 
2732     // Lambdas can be compared with __traits(isSame, ...),
2733     // so they can be compared with isSameSymbol.
2734     static assert( isSameSymbol!(a => a + 42, a => a + 42));
2735     static assert(!isSameSymbol!(a => a + 42, a => a + 99));
2736 
2737     // Partial instantiation allows it to be used with templates that expect
2738     // a predicate that takes only a single argument.
2739     import phobos.sys.meta : AliasSeq, indexOf;
2740     alias Types = AliasSeq!(i, j, r, int, long, foo);
2741     static assert(indexOf!(isSameSymbol!j, Types) == 1);
2742     static assert(indexOf!(isSameSymbol!int, Types) == 3);
2743     static assert(indexOf!(isSameSymbol!bar, Types) == -1);
2744 }
2745 
2746 /++
2747     Whether the given types are the same type.
2748 
2749     All this does is $(D is(T == U)), so most code shouldn't use it. It's
2750     intended to be used in conjunction with templates that take a template
2751     predicate - such as those in phobos.sys.meta.
2752 
2753     The single-argument overload makes it so that it can be partially
2754     instantiated with the first argument, which will often be necessary with
2755     template predicates.
2756 
2757     See_Also:
2758         $(LREF isEqual)
2759         $(LREF isSameSymbol)
2760   +/
2761 enum isSameType(T, U) = is(T == U);
2762 
2763 /++ Ditto +/
2764 template isSameType(T)
2765 {
2766     enum isSameType(U) = is(T == U);
2767 }
2768 
2769 ///
2770 @safe unittest
2771 {
2772     static assert( isSameType!(long, long));
2773     static assert(!isSameType!(long, const long));
2774     static assert(!isSameType!(long, string));
2775     static assert( isSameType!(string, string));
2776 
2777     int i;
2778     real r;
2779     static assert( isSameType!(int, typeof(i)));
2780     static assert(!isSameType!(int, typeof(r)));
2781 
2782     static assert(!isSameType!(real, typeof(i)));
2783     static assert( isSameType!(real, typeof(r)));
2784 
2785     // Partial instantiation allows it to be used with templates that expect
2786     // a predicate that takes only a single argument.
2787     import phobos.sys.meta : AliasSeq, indexOf;
2788     alias Types = AliasSeq!(float, string, int, double);
2789     static assert(indexOf!(isSameType!int, Types) == 2);
2790 }
2791 
2792 /++
2793     Evaluates to $(K_TRUE) ifthe given type is a delegate (and to $(K_FALSE)
2794     otherwise).
2795 
2796     This is equivalent to $(D is(T == delegate)), so most code shouldn't use
2797     it. It's intended to be used in conjunction with templates that take a
2798     template predicate - such as those in $(MREF phobos, sys, meta).
2799 
2800     Note that this does not include implicit conversions or enum types. The
2801     type itself must be a delegate.
2802 
2803     Whether taking the address of a function results in a function pointer or a
2804     delegate depends on whether the result includes a context pointer.
2805 
2806     Taking the address of a free function or a $(K_STATIC) function gives a
2807     function pointer. Taking the address of a non-$(K_STATIC) nested function
2808     gives a delegate. And the potentially confusing one is non-$(K_STATIC)
2809     member functions, because whether taking their address results in a
2810     function pointer or a delegate depends on whether the address is taken via
2811     the type or via an instance.
2812 
2813     See the documentation for $(LREF SymbolType) and $(LREF PropertyType) to
2814     see the quirks involving $(K_PROPERTY) and why either $(LREF SymbolType) or
2815     $(LREF PropertyType) should be used rather than $(K_TYPEOF) to get the type
2816     of a symbol.
2817 
2818     See_Also:
2819         $(LREF isFunction)
2820         $(LREF isFunctionPointer)
2821         $(LREF isReturn)
2822         $(LREF PropertyType)
2823         $(LREF SymbolType)
2824         $(LREF ToFunctionType)
2825   +/
2826 enum isDelegate(T) = is(T == delegate);
2827 
2828 ///
2829 @safe unittest
2830 {
2831     int var;
2832     static assert(!isDelegate!(SymbolType!var));
2833     static assert(!isDelegate!(PropertyType!var));
2834     static assert(!isDelegate!(typeof(&var)));
2835     static assert(!is(SymbolType!var == delegate));
2836     static assert(!is(PropertType!var == delegate));
2837     static assert(!is(typeof(&var) == delegate));
2838 
2839     static void func() {}
2840     static assert(!isDelegate!(SymbolType!func));
2841     static assert(!isDelegate!(typeof(&func)));
2842     static assert(!is(SymbolType!func == delegate));
2843     static assert(!is(typeof(&func) == delegate));
2844 
2845     void funcWithContext() { ++var; }
2846     static assert(!isDelegate!(SymbolType!funcWithContext));
2847     static assert( isDelegate!(typeof(&funcWithContext)));
2848     static assert(!is(SymbolType!funcWithContext == delegate));
2849     static assert( is(typeof(&funcWithContext) == delegate));
2850 
2851     int function() funcPtr;
2852     static assert(!isDelegate!(SymbolType!funcPtr));
2853     static assert(!isDelegate!(PropertyType!funcPtr));
2854     static assert(!isDelegate!(typeof(&funcPtr)));
2855     static assert(!is(SymbolType!funcPtr == delegate));
2856     static assert(!is(PropertyType!funcPtr == delegate));
2857     static assert(!is(typeof(&funcPtr) == delegate));
2858 
2859     int delegate() del;
2860     static assert( isDelegate!(SymbolType!del));
2861     static assert( isDelegate!(PropertyType!del));
2862     static assert(!isDelegate!(typeof(&del)));
2863     static assert( is(SymbolType!del == delegate));
2864     static assert( is(PropertyType!del == delegate));
2865     static assert(!is(typeof(&del) == delegate));
2866 
2867     @property static int prop() { return 0; }
2868     static assert(!isDelegate!(SymbolType!prop));
2869     static assert(!isDelegate!(PropertyType!prop));
2870     static assert(!isDelegate!(typeof(&prop)));
2871     static assert(!is(SymbolType!prop == delegate));
2872     static assert(!is(PropertyType!prop == delegate));
2873     static assert(!is(typeof(&prop) == delegate));
2874 
2875     @property int propWithContext() { return var; }
2876     static assert(!isDelegate!(SymbolType!propWithContext));
2877     static assert(!isDelegate!(PropertyType!propWithContext));
2878     static assert( isDelegate!(typeof(&propWithContext)));
2879     static assert(!is(SymbolType!propWithContext == delegate));
2880     static assert(!is(PropertyType!propWithContext == delegate));
2881     static assert( is(typeof(&propWithContext) == delegate));
2882 
2883     static int function() propFuncPtr() @property { return null; }
2884     static assert(!isDelegate!(SymbolType!propFuncPtr));
2885     static assert(!isDelegate!(PropertyType!propFuncPtr));
2886     static assert(!isDelegate!(typeof(&propFuncPtr)));
2887     static assert(!is(SymbolType!propFuncPtr == delegate));
2888     static assert(!is(PropertyType!propFuncPtr == delegate));
2889     static assert(!is(typeof(&propFuncPtr) == delegate));
2890 
2891     static int delegate() propDel() @property { return null; }
2892     static assert(!isDelegate!(SymbolType!propDel));
2893     static assert( isDelegate!(PropertyType!propDel));
2894     static assert(!isDelegate!(typeof(&propDel)));
2895     static assert(!is(SymbolType!propDel == delegate));
2896     static assert( is(PropertyType!propDel == delegate));
2897     static assert(!is(typeof(&propDel) == delegate));
2898 
2899     static struct S
2900     {
2901         void foo() {}
2902     }
2903     static assert(!isDelegate!(SymbolType!(S.foo)));
2904     static assert(!isDelegate!(typeof(&S.foo)));
2905     static assert( isDelegate!(typeof(&S.init.foo)));
2906     static assert(!is(SymbolType!(S.foo) == delegate));
2907     static assert(!is(typeof(&S.foo) == delegate));
2908     static assert( is(typeof(&S.init.foo) == delegate));
2909 
2910     struct HasContext
2911     {
2912         void foo() { ++var; }
2913     }
2914     static assert(!isDelegate!(SymbolType!(S.foo)));
2915     static assert(!isDelegate!(typeof(&S.foo)));
2916     static assert( isDelegate!(typeof(&S.init.foo)));
2917     static assert(!is(SymbolType!(S.foo) == delegate));
2918     static assert(!is(typeof(&S.foo) == delegate));
2919     static assert( is(typeof(&S.init.foo) == delegate));
2920 }
2921 
2922 /++
2923     Evaluates to $(K_TRUE) if the given type is a function (and to $(K_FALSE)
2924     otherwise).
2925 
2926     This is equivalent to $(D is(T == function)), so most code shouldn't use
2927     it. It's intended to be used in conjunction with templates that take a
2928     template predicate - such as those in $(MREF phobos, sys, meta).
2929 
2930     Note that this does not include implicit conversions or enum types. The
2931     type itself must be a function.
2932 
2933     It's not currently possible in D to type out the type of a function on its
2934     own, so normally, the only way to get a function type is to get the type of
2935     a symbol which is a function. However, $(LREF ToFunctionType) can be used
2936     to convert a function pointer type to a function type for code that needs
2937     that, though that's likely only to come up in $(K_IS) expressions.
2938 
2939     See the documentation for $(LREF SymbolType) and $(LREF PropertyType) to
2940     see the quirks involving $(K_PROPERTY) and why either $(LREF SymbolType) or
2941     $(LREF PropertyType) should be used rather than $(K_TYPEOF) to get the type
2942     of a symbol.
2943 
2944     See_Also:
2945         $(LREF isDelegate)
2946         $(LREF isFunctionPointer)
2947         $(LREF isReturn)
2948         $(LREF PropertyType)
2949         $(LREF SymbolType)
2950         $(LREF ToFunctionType)
2951   +/
2952 enum isFunction(T) = is(T == function);
2953 
2954 ///
2955 @safe unittest
2956 {
2957     int var;
2958     static assert(!isFunction!(SymbolType!var));
2959     static assert(!isFunction!(PropertyType!var));
2960     static assert(!isFunction!(typeof(&var)));
2961     static assert(!is(SymbolType!var == function));
2962     static assert(!is(PropertType!var == function));
2963     static assert(!is(typeof(&var) == function));
2964 
2965     static void func() {}
2966     static assert( isFunction!(SymbolType!func));
2967     static assert(!isFunction!(typeof(&func)));
2968     static assert( is(SymbolType!func == function));
2969     static assert(!is(typeof(&func) == function));
2970 
2971     void funcWithContext() { ++var; }
2972     static assert( isFunction!(SymbolType!funcWithContext));
2973     static assert(!isFunction!(typeof(&funcWithContext)));
2974     static assert( is(SymbolType!funcWithContext == function));
2975     static assert(!is(typeof(&funcWithContext) == function));
2976 
2977     int function() funcPtr;
2978     static assert(!isFunction!(SymbolType!funcPtr));
2979     static assert(!isFunction!(PropertyType!funcPtr));
2980     static assert(!isFunction!(typeof(&funcPtr)));
2981     static assert(!is(SymbolType!funcPtr == function));
2982     static assert(!is(PropertyType!funcPtr == function));
2983     static assert(!is(typeof(&funcPtr) == function));
2984 
2985     int delegate() del;
2986     static assert(!isFunction!(SymbolType!del));
2987     static assert(!isFunction!(PropertyType!del));
2988     static assert(!isFunction!(typeof(&del)));
2989     static assert(!is(SymbolType!del == function));
2990     static assert(!is(PropertyType!del == function));
2991     static assert(!is(typeof(&del) == function));
2992 
2993     // It's possible to get the pointers to the function and the context from a
2994     // delegate in @system code.
2995     static assert( isFunctionPointer!(typeof(SymbolType!del.funcptr)));
2996     static assert( is(typeof(SymbolType!del.ptr) == void*));
2997 
2998     @property static int prop() { return 0; }
2999     static assert( isFunction!(SymbolType!prop));
3000     static assert(!isFunction!(PropertyType!prop));
3001     static assert(!isFunction!(typeof(&prop)));
3002     static assert( is(SymbolType!prop == function));
3003     static assert(!is(PropertyType!prop == function));
3004     static assert(!is(typeof(&prop) == function));
3005 
3006     @property int propWithContext() { return var; }
3007     static assert( isFunction!(SymbolType!propWithContext));
3008     static assert(!isFunction!(PropertyType!propWithContext));
3009     static assert(!isFunction!(typeof(&propWithContext)));
3010     static assert( is(SymbolType!propWithContext == function));
3011     static assert(!is(PropertyType!propWithContext == function));
3012     static assert(!is(typeof(&propWithContext) == function));
3013 
3014     static int function() propFuncPtr() @property { return null; }
3015     static assert( isFunction!(SymbolType!propFuncPtr));
3016     static assert(!isFunction!(PropertyType!propFuncPtr));
3017     static assert(!isFunction!(typeof(&propFuncPtr)));
3018     static assert( is(SymbolType!propFuncPtr == function));
3019     static assert(!is(PropertyType!propFuncPtr == function));
3020     static assert(!is(typeof(&propFuncPtr) == function));
3021 
3022     static int delegate() propDel() @property { return null; }
3023     static assert( isFunction!(SymbolType!propDel));
3024     static assert(!isFunction!(PropertyType!propDel));
3025     static assert(!isFunction!(typeof(&propDel)));
3026     static assert( is(SymbolType!propDel == function));
3027     static assert(!is(PropertyType!propDel == function));
3028     static assert(!is(typeof(&propDel) == function));
3029 
3030     static struct S
3031     {
3032         void foo() {}
3033     }
3034     static assert( isFunction!(SymbolType!(S.foo)));
3035     static assert(!isFunction!(typeof(&S.foo)));
3036     static assert(!isFunction!(typeof(&S.init.foo)));
3037     static assert( is(SymbolType!(S.foo) == function));
3038     static assert(!is(typeof(&S.foo) == function));
3039     static assert(!is(typeof(&S.init.foo) == function));
3040 
3041     struct HasContext
3042     {
3043         void foo() { ++var; }
3044     }
3045     static assert( isFunction!(SymbolType!(S.foo)));
3046     static assert(!isFunction!(typeof(&S.foo)));
3047     static assert(!isFunction!(typeof(&S.init.foo)));
3048     static assert( is(SymbolType!(S.foo) == function));
3049     static assert(!is(typeof(&S.foo) == function));
3050     static assert(!is(typeof(&S.init.foo) == function));
3051 }
3052 
3053 /++
3054     Evaluates to $(K_TRUE) if the given type is a function pointer (and to
3055     $(K_FALSE) otherwise).
3056 
3057     Note that this does not include implicit conversions or enum types. The
3058     type itself must be a function pointer.
3059 
3060     Whether taking the address of a function results in a function pointer or a
3061     delegate depends on whether the result includes a context pointer.
3062 
3063     Taking the address of a free function or a $(K_STATIC) function gives a
3064     function pointer. Taking the address of a non-$(K_STATIC) nested function
3065     gives a delegate. And the potentially confusing one is non-$(K_STATIC)
3066     member functions, because whether taking their address results in a
3067     function pointer or a delegate depends on whether the address is taken via
3068     the type or via an instance.
3069 
3070     See the documentation for $(LREF SymbolType) and $(LREF PropertyType) to
3071     see the quirks involving $(K_PROPERTY) and why either $(LREF SymbolType) or
3072     $(LREF PropertyType) should be used rather than $(K_TYPEOF) to get the type
3073     of a symbol.
3074 
3075     See_Also:
3076         $(LREF isDelegate)
3077         $(LREF isFunction)
3078         $(LREF isReturn)
3079         $(LREF PropertyType)
3080         $(LREF SymbolType)
3081         $(LREF ToFunctionType)
3082   +/
3083 enum isFunctionPointer(T) = is(T == U*, U) && is(U == function);
3084 
3085 ///
3086 @safe unittest
3087 {
3088     int var;
3089     static assert(!isFunctionPointer!(SymbolType!var));
3090     static assert(!isFunctionPointer!(PropertyType!var));
3091     static assert(!isFunctionPointer!(typeof(&var)));
3092 
3093     static void func() {}
3094     static assert(!isFunctionPointer!(SymbolType!func));
3095     static assert( isFunctionPointer!(typeof(&func)));
3096 
3097     void funcWithContext() { ++var; }
3098     static assert(!isFunctionPointer!(SymbolType!funcWithContext));
3099     static assert(!isFunctionPointer!(typeof(&funcWithContext)));
3100 
3101     int function() funcPtr;
3102     static assert( isFunctionPointer!(SymbolType!funcPtr));
3103     static assert( isFunctionPointer!(PropertyType!funcPtr));
3104     static assert(!isFunctionPointer!(typeof(&funcPtr)));
3105 
3106     int delegate() del;
3107     static assert(!isFunctionPointer!(SymbolType!del));
3108     static assert(!isFunctionPointer!(PropertyType!del));
3109     static assert(!isFunctionPointer!(typeof(&del)));
3110 
3111     // It's possible to get the pointers to the function and the context from a
3112     // delegate in @system code.
3113     static assert( isFunctionPointer!(typeof(SymbolType!del.funcptr)));
3114     static assert( is(typeof(SymbolType!del.ptr) == void*));
3115 
3116     @property static int prop() { return 0; }
3117     static assert(!isFunctionPointer!(SymbolType!prop));
3118     static assert(!isFunctionPointer!(PropertyType!prop));
3119     static assert( isFunctionPointer!(typeof(&prop)));
3120 
3121     @property int propWithContext() { return var; }
3122     static assert(!isFunctionPointer!(SymbolType!propWithContext));
3123     static assert(!isFunctionPointer!(PropertyType!propWithContext));
3124     static assert(!isFunctionPointer!(typeof(&propWithContext)));
3125 
3126     static int function() propFuncPtr() @property { return null; }
3127     static assert(!isFunctionPointer!(SymbolType!propFuncPtr));
3128     static assert( isFunctionPointer!(PropertyType!propFuncPtr));
3129     static assert( isFunctionPointer!(typeof(&propFuncPtr)));
3130 
3131     static int delegate() propDel() @property { return null; }
3132     static assert(!isFunctionPointer!(SymbolType!propDel));
3133     static assert(!isFunctionPointer!(PropertyType!propDel));
3134     static assert( isFunctionPointer!(typeof(&propDel)));
3135 
3136     static struct S
3137     {
3138         void foo() {}
3139     }
3140     static assert(!isFunctionPointer!(SymbolType!(S.foo)));
3141     static assert( isFunctionPointer!(typeof(&S.foo)));
3142     static assert(!isFunctionPointer!(typeof(&S.init.foo)));
3143 
3144     struct HasContext
3145     {
3146         void foo() { ++var; }
3147     }
3148     static assert(!isFunctionPointer!(SymbolType!(S.foo)));
3149     static assert( isFunctionPointer!(typeof(&S.foo)));
3150     static assert(!isFunctionPointer!(typeof(&S.init.foo)));
3151 }
3152 
3153 /++
3154     Evaluates to $(K_TRUE) if the given type is a function, function pointer,
3155     or delegate (and to $(K_FALSE) otherwise).
3156 
3157     This is equivalent to $(D is(T == return)), so most code shouldn't use
3158     it. It's intended to be used in conjunction with templates that take a
3159     template predicate - such as those in $(MREF phobos, sys, meta).
3160 
3161     Note that this does not include implicit conversions or enum types. The
3162     type itself must be a function, function pointer, or delegate.
3163 
3164     See the documentation for $(LREF SymbolType) and $(LREF PropertyType) to
3165     see the quirks involving $(K_PROPERTY) and why either $(LREF SymbolType) or
3166     $(LREF PropertyType) should be used rather than $(K_TYPEOF) to get the type
3167     of a symbol.
3168 
3169     See_Also:
3170         $(LREF isDelegate)
3171         $(LREF isFunction)
3172         $(LREF isFunctionPointer)
3173         $(LREF PropertyType)
3174         $(LREF SymbolType)
3175         $(LREF ToFunctionType)
3176   +/
3177 enum isReturn(T) = is(T == return);
3178 
3179 ///
3180 @safe unittest
3181 {
3182     int var;
3183     static assert(!isReturn!(SymbolType!var));
3184     static assert(!isReturn!(PropertyType!var));
3185     static assert(!isReturn!(typeof(&var)));
3186     static assert(!is(SymbolType!var == return));
3187     static assert(!is(PropertType!var == return));
3188     static assert(!is(typeof(&var) == return));
3189 
3190     static void func() {}
3191     static assert( isReturn!(SymbolType!func));
3192     static assert( isReturn!(typeof(&func)));
3193     static assert( is(SymbolType!func == return));
3194     static assert( is(typeof(&func) == return));
3195 
3196     void funcWithContext() { ++var; }
3197     static assert( isReturn!(SymbolType!funcWithContext));
3198     static assert( isReturn!(typeof(&funcWithContext)));
3199     static assert( is(SymbolType!funcWithContext == return));
3200     static assert( is(typeof(&funcWithContext) == return));
3201 
3202     int function() funcPtr;
3203     static assert( isReturn!(SymbolType!funcPtr));
3204     static assert( isReturn!(PropertyType!funcPtr));
3205     static assert(!isReturn!(typeof(&funcPtr)));
3206     static assert( is(SymbolType!funcPtr == return));
3207     static assert( is(PropertyType!funcPtr == return));
3208     static assert(!is(typeof(&funcPtr) == return));
3209 
3210     int delegate() del;
3211     static assert( isReturn!(SymbolType!del));
3212     static assert( isReturn!(PropertyType!del));
3213     static assert(!isReturn!(typeof(&del)));
3214     static assert( is(SymbolType!del == return));
3215     static assert( is(PropertyType!del == return));
3216     static assert(!is(typeof(&del) == return));
3217 
3218     // It's possible to get the pointers to the function and the context from a
3219     // delegate in @system code.
3220     static assert( isFunctionPointer!(typeof(SymbolType!del.funcptr)));
3221     static assert( is(typeof(SymbolType!del.ptr) == void*));
3222 
3223     @property static int prop() { return 0; }
3224     static assert( isReturn!(SymbolType!prop));
3225     static assert(!isReturn!(PropertyType!prop));
3226     static assert( isReturn!(typeof(&prop)));
3227     static assert( is(SymbolType!prop == return));
3228     static assert(!is(PropertyType!prop == return));
3229     static assert( is(typeof(&prop) == return));
3230 
3231     @property int propWithContext() { return var; }
3232     static assert( isReturn!(SymbolType!propWithContext));
3233     static assert(!isReturn!(PropertyType!propWithContext));
3234     static assert( isReturn!(typeof(&propWithContext)));
3235     static assert( is(SymbolType!propWithContext == return));
3236     static assert(!is(PropertyType!propWithContext == return));
3237     static assert( is(typeof(&propWithContext) == return));
3238 
3239     static int function() propFuncPtr() @property { return null; }
3240     static assert( isReturn!(SymbolType!propFuncPtr));
3241     static assert( isReturn!(PropertyType!propFuncPtr));
3242     static assert( isReturn!(typeof(&propFuncPtr)));
3243     static assert( is(SymbolType!propFuncPtr == return));
3244     static assert( is(PropertyType!propFuncPtr == return));
3245     static assert( is(typeof(&propFuncPtr) == return));
3246 
3247     static int delegate() propDel() @property { return null; }
3248     static assert( isReturn!(SymbolType!propDel));
3249     static assert( isReturn!(PropertyType!propDel));
3250     static assert( isReturn!(typeof(&propDel)));
3251     static assert( is(SymbolType!propDel == return));
3252     static assert( is(PropertyType!propDel == return));
3253     static assert( is(typeof(&propDel) == return));
3254 
3255     static struct S
3256     {
3257         void foo() {}
3258     }
3259     static assert( isReturn!(SymbolType!(S.foo)));
3260     static assert( isReturn!(typeof(&S.foo)));
3261     static assert( isReturn!(typeof(&S.init.foo)));
3262     static assert( is(SymbolType!(S.foo) == return));
3263     static assert( is(typeof(&S.foo) == return));
3264     static assert( is(typeof(&S.init.foo) == return));
3265 
3266     struct HasContext
3267     {
3268         void foo() { ++var; }
3269     }
3270     static assert( isReturn!(SymbolType!(S.foo)));
3271     static assert( isReturn!(typeof(&S.foo)));
3272     static assert( isReturn!(typeof(&S.init.foo)));
3273     static assert( is(SymbolType!(S.foo) == return));
3274     static assert( is(typeof(&S.foo) == return));
3275     static assert( is(typeof(&S.init.foo) == return));
3276 }
3277 
3278 /++
3279     Converts a function type, function pointer type, or delegate type to the
3280     corresponding function type.
3281 
3282     For a function, the result is the same as the given type.
3283 
3284     For a function pointer or delegate, the result is the same as it would be
3285     for a function with the same return type, the same set of parameters, and
3286     the same set of attributes.
3287 
3288     Another way to look at it would be that it's the type that comes from
3289     dereferencing the function pointer. And while it's not technically possible
3290     to dereference a delegate, it's conceptually the same thing, since a
3291     delegate is essentially a fat pointer to a function in the sense that it
3292     contains a pointer to a function and a pointer to the function's context.
3293     The result of ToFunctionType is the type of that function.
3294 
3295     Note that code which has a symbol which is a function should use
3296     $(LREF SymbolType) rather than $(K_TYPEOF) to get the type of the function
3297     in order to avoid issues with regards to $(K_PROPERTY) (see the
3298     documentation for $(LREF SymbolType) for details).
3299 
3300     See_Also:
3301         $(LREF SymbolType)
3302   +/
3303 template ToFunctionType(T)
3304 if (is(T == return))
3305 {
3306     // Function pointers.
3307     static if (is(T == U*, U) && is(U == function))
3308         alias ToFunctionType = U;
3309     // Delegates.
3310     else static if (is(T U == delegate))
3311         alias ToFunctionType = U;
3312     // Functions.
3313     else
3314         alias ToFunctionType = T;
3315 }
3316 
3317 ///
3318 @safe unittest
3319 {
3320     static string func(int) { return ""; }
3321     auto funcPtr = &func;
3322 
3323     static assert( is(ToFunctionType!(SymbolType!func) == SymbolType!func));
3324     static assert( is(ToFunctionType!(SymbolType!funcPtr) == SymbolType!func));
3325     static assert(!is(SymbolType!funcPtr == function));
3326     static assert( is(ToFunctionType!(SymbolType!funcPtr) == function));
3327 
3328     int var;
3329     int funcWithContext(string) { return var; }
3330     auto funcDel = &funcWithContext;
3331 
3332     static assert( is(ToFunctionType!(SymbolType!funcWithContext) ==
3333                       SymbolType!funcWithContext));
3334     static assert( is(ToFunctionType!(SymbolType!funcDel) ==
3335                       SymbolType!funcWithContext));
3336     static assert( is(SymbolType!funcWithContext == function));
3337     static assert(!is(SymbolType!funcDel == function));
3338     static assert( is(SymbolType!funcDel == delegate));
3339     static assert( is(ToFunctionType!(SymbolType!funcDel) == function));
3340 
3341     static @property int prop() { return 0; }
3342     static assert( is(SymbolType!prop == function));
3343     static assert(!is(SymbolType!prop == delegate));
3344     static assert( is(SymbolType!prop == return));
3345     static assert( is(SymbolType!prop ==
3346                       ToFunctionType!(int function() @property @safe pure
3347                                                      nothrow @nogc)));
3348     static assert( is(ToFunctionType!(SymbolType!prop) == SymbolType!prop));
3349 
3350     // This is an example of why SymbolType should be used rather than typeof
3351     // when using ToFunctionType (or getting the type of any symbol which might
3352     // be a function when you want the actual type of the symbol and don't want
3353     // to end up with its return type instead).
3354     static assert( is(typeof(prop) == int));
3355     static assert(!is(typeof(prop) == function));
3356     static assert(!__traits(compiles, ToFunctionType!(typeof(prop))));
3357 
3358     auto propPtr = ∝
3359     static assert(!is(typeof(propPtr) == function));
3360     static assert(!is(SymbolType!propPtr == function));
3361     static assert( isFunctionPointer!(typeof(propPtr)));
3362     static assert( is(ToFunctionType!(SymbolType!propPtr) == function));
3363 
3364     static assert( is(SymbolType!propPtr ==
3365                       int function() @property @safe pure nothrow @nogc));
3366     static assert(!is(ToFunctionType!(SymbolType!propPtr) ==
3367                       int function() @property @safe pure nothrow @nogc));
3368     static assert( is(ToFunctionType!(SymbolType!propPtr) ==
3369                       ToFunctionType!(int function() @property @safe pure
3370                                                      nothrow @nogc)));
3371 
3372     @property void propWithContext(int i) { var += i; }
3373     static assert( is(SymbolType!propWithContext == function));
3374     static assert( is(SymbolType!propWithContext ==
3375                       ToFunctionType!(void function(int) @property @safe pure
3376                                                          nothrow @nogc)));
3377     static assert( is(ToFunctionType!(SymbolType!propWithContext) ==
3378                       SymbolType!propWithContext));
3379 
3380     // typeof fails to compile with setter properties, complaining about there
3381     // not being enough arguments, because it's treating the function as an
3382     // expression - and since such an expression would call the function, the
3383     // expression isn't valid if there aren't enough function arguments.
3384     static assert(!__traits(compiles, typeof(propWithContext)));
3385 
3386     auto propDel = &propWithContext;
3387     static assert(!is(SymbolType!propDel == function));
3388     static assert( is(SymbolType!propDel == delegate));
3389     static assert( is(SymbolType!propDel == return));
3390     static assert( is(ToFunctionType!(SymbolType!propDel) == function));
3391     static assert( is(ToFunctionType!(SymbolType!propDel) ==
3392                       SymbolType!propWithContext));
3393 
3394     static assert( is(SymbolType!propDel ==
3395                       void delegate(int) @property @safe pure nothrow @nogc));
3396     static assert(!is(ToFunctionType!(SymbolType!propDel) ==
3397                       void delegate(int) @property @safe pure nothrow @nogc));
3398     static assert(!is(ToFunctionType!(SymbolType!propDel) ==
3399                       void function(int) @property @safe pure nothrow @nogc));
3400     static assert( is(ToFunctionType!(SymbolType!propDel) ==
3401                       ToFunctionType!(void function(int) @property @safe pure
3402                                                          nothrow @nogc)));
3403 
3404     // Delegates have a funcptr property and a ptr property (which can only be
3405     // used in @system code) which give the pointer to the function and the
3406     // pointer to the context respectively.
3407     static assert( is(ToFunctionType!(SymbolType!propDel) ==
3408                       typeof(*SymbolType!propDel.funcptr)));
3409     static assert( is(typeof(SymbolType!propDel.ptr) == void*));
3410 
3411     static struct S
3412     {
3413         string foo(int);
3414         string bar(int, int);
3415         @property void prop(string);
3416     }
3417 
3418     static assert( is(ToFunctionType!(SymbolType!(S.foo)) ==
3419                       ToFunctionType!(string function(int))));
3420     static assert( is(ToFunctionType!(SymbolType!(S.bar)) ==
3421                       ToFunctionType!(string function(int, int))));
3422     static assert( is(ToFunctionType!(SymbolType!(S.prop)) ==
3423                       ToFunctionType!(void function(string) @property)));
3424 }
3425 
3426 @safe unittest
3427 {
3428     // Unfortunately, in this case, we get linker errors when taking the address
3429     // of the functions if we avoid inference by not giving function bodies.
3430     // So if we don't want to list all of those attributes in the tests, we have
3431     // to stop the inference in another way.
3432     static int var;
3433     static void killAttributes() @system { ++var; throw new Exception("message"); }
3434 
3435     static struct S
3436     {
3437         int func1() { killAttributes(); return 0; }
3438         void func2(int) { killAttributes(); }
3439 
3440         static int func3() { killAttributes(); return 0; }
3441         static void func4(int) { killAttributes(); }
3442 
3443         @property int func5() { killAttributes(); return 0; }
3444         @property void func6(int) { killAttributes(); }
3445     }
3446 
3447     static assert( is(SymbolType!(S.func1) == ToFunctionType!(int function())));
3448     static assert( is(SymbolType!(S.func2) == ToFunctionType!(void function(int))));
3449     static assert( is(SymbolType!(S.func3) == ToFunctionType!(int function())));
3450     static assert( is(SymbolType!(S.func4) == ToFunctionType!(void function(int))));
3451     static assert( is(SymbolType!(S.func5) == ToFunctionType!(int function() @property)));
3452     static assert( is(SymbolType!(S.func6) == ToFunctionType!(void function(int) @property)));
3453 
3454     static assert( is(ToFunctionType!(SymbolType!(S.func1)) == ToFunctionType!(int function())));
3455     static assert( is(ToFunctionType!(SymbolType!(S.func2)) == ToFunctionType!(void function(int))));
3456     static assert( is(ToFunctionType!(SymbolType!(S.func3)) == ToFunctionType!(int function())));
3457     static assert( is(ToFunctionType!(SymbolType!(S.func4)) == ToFunctionType!(void function(int))));
3458     static assert( is(ToFunctionType!(SymbolType!(S.func5)) == ToFunctionType!(int function() @property)));
3459     static assert( is(ToFunctionType!(SymbolType!(S.func6)) ==
3460                       ToFunctionType!(void function(int) @property)));
3461 
3462     auto ptr1 = &S.init.func1;
3463     auto ptr2 = &S.init.func2;
3464     auto ptr3 = &S.func3;
3465     auto ptr4 = &S.func4;
3466     auto ptr5 = &S.init.func5;
3467     auto ptr6 = &S.init.func6;
3468 
3469     // For better or worse, static member functions can be accessed through
3470     // instance of the type as well as through the type.
3471     auto ptr3Instance = &S.init.func3;
3472     auto ptr4Instance = &S.init.func4;
3473 
3474     static assert( is(SymbolType!ptr1 == int delegate()));
3475     static assert( is(SymbolType!ptr2 == void delegate(int)));
3476     static assert( is(SymbolType!ptr3 == int function()));
3477     static assert( is(SymbolType!ptr4 == void function(int)));
3478     static assert( is(SymbolType!ptr5 == int delegate() @property));
3479     static assert( is(SymbolType!ptr6 == void delegate(int) @property));
3480 
3481     static assert( is(SymbolType!ptr3Instance == int function()));
3482     static assert( is(SymbolType!ptr4Instance == void function(int)));
3483 
3484     static assert( is(ToFunctionType!(SymbolType!ptr1) == ToFunctionType!(int function())));
3485     static assert( is(ToFunctionType!(SymbolType!ptr2) == ToFunctionType!(void function(int))));
3486     static assert( is(ToFunctionType!(SymbolType!ptr3) == ToFunctionType!(int function())));
3487     static assert( is(ToFunctionType!(SymbolType!ptr4) == ToFunctionType!(void function(int))));
3488     static assert( is(ToFunctionType!(SymbolType!ptr5) == ToFunctionType!(int function() @property)));
3489     static assert( is(ToFunctionType!(SymbolType!ptr6) == ToFunctionType!(void function(int) @property)));
3490 
3491     static assert( is(ToFunctionType!(SymbolType!ptr3Instance) == ToFunctionType!(int function())));
3492     static assert( is(ToFunctionType!(SymbolType!ptr4Instance) == ToFunctionType!(void function(int))));
3493 }
3494 
3495 /++
3496     Evaluates to an $(D AliasSeq) of the names (as $(D string)s) of the member
3497     variables of an aggregate type (i.e. a struct, class, interface, or union).
3498 
3499     These are fields which take up memory space within an instance of the type
3500     (i.e. not enums / manifest constants, since they don't take up memory
3501     space, and not static member variables, since they don't take up memory
3502     space within an instance).
3503 
3504     Hidden fields (like the virtual function table pointer or the context
3505     pointer for nested types) are not included.
3506 
3507     For classes, only the direct member variables are included and not those
3508     of any base classes.
3509 
3510     For interfaces, the result of FieldNames is always empty, because
3511     interfaces cannot have member variables. However, because interfaces are
3512     aggregate types, they work with FieldNames for consistency so that code
3513     that's written to work on aggregate types doesn't have to worry about
3514     whether it's dealing with an interface.
3515 
3516     See_Also:
3517         $(LREF FieldSymbols)
3518         $(LREF FieldTypes)
3519         $(DDSUBLINK spec/struct.html, struct_instance_properties, $(D tupleof))
3520   +/
3521 template FieldNames(T)
3522 if (isAggregateType!T)
3523 {
3524     import phobos.sys.meta : AliasSeq;
3525 
3526     static if (is(T == struct) && __traits(isNested, T))
3527         private alias Fields = AliasSeq!(T.tupleof[0 .. $ - 1]);
3528     else
3529         private alias Fields = T.tupleof;
3530 
3531     alias FieldNames = AliasSeq!();
3532     static foreach (Field; Fields)
3533         FieldNames = AliasSeq!(FieldNames, Field.stringof);
3534 }
3535 
3536 ///
3537 @safe unittest
3538 {
3539     import phobos.sys.meta : AliasSeq;
3540 
3541     struct S
3542     {
3543         int x;
3544         float y;
3545     }
3546     static assert(FieldNames!S == AliasSeq!("x", "y"));
3547 
3548     // Since the AliasSeq contains values, all of which are of the same type,
3549     // it can be used to create a dynamic array, which would be more
3550     // efficient than operating on an AliasSeq in the cases where an
3551     // AliasSeq is not necessary.
3552     static assert([FieldNames!S] == ["x", "y"]);
3553 
3554     class C
3555     {
3556         // static variables are not included.
3557         static int var;
3558 
3559         // Manifest constants are not included.
3560         enum lang = "dlang";
3561 
3562         // Functions are not included, even if they're @property functions.
3563         @property int foo() { return 42; }
3564 
3565         string s;
3566         int i;
3567         int[] arr;
3568     }
3569     static assert(FieldNames!C == AliasSeq!("s", "i", "arr"));
3570 
3571     static assert([FieldNames!C] == ["s", "i", "arr"]);
3572 
3573     // Only direct member variables are included. Member variables from any base
3574     // classes are not.
3575     class D : C
3576     {
3577         real r;
3578     }
3579     static assert(FieldNames!D == AliasSeq!"r");
3580 
3581     static assert([FieldNames!D] == ["r"]);
3582 
3583     // FieldNames will always be empty for an interface, since it's not legal
3584     // for interfaces to have member variables.
3585     interface I
3586     {
3587     }
3588     static assert(FieldNames!I.length == 0);
3589 
3590     union U
3591     {
3592         int i;
3593         double d;
3594         long l;
3595         S s;
3596     }
3597     static assert(FieldNames!U == AliasSeq!("i", "d", "l", "s"));
3598 
3599     static assert([FieldNames!U] == ["i", "d", "l", "s"]);;
3600 
3601     // FieldNames only operates on aggregate types.
3602     static assert(!__traits(compiles, FieldNames!int));
3603     static assert(!__traits(compiles, FieldNames!(S*)));
3604     static assert(!__traits(compiles, FieldNames!(C[])));
3605 }
3606 
3607 @safe unittest
3608 {
3609     import phobos.sys.meta : AliasSeq;
3610 
3611     {
3612         static struct S0 {}
3613         static assert(FieldNames!S0.length == 0);
3614 
3615         static struct S1 { int a; }
3616         static assert(FieldNames!S1 == AliasSeq!"a");
3617 
3618         static struct S2 { int a; string b; }
3619         static assert(FieldNames!S2 == AliasSeq!("a", "b"));
3620 
3621         static struct S3 { int a; string b; real c; }
3622         static assert(FieldNames!S3 == AliasSeq!("a", "b", "c"));
3623     }
3624     {
3625         int i;
3626         struct S0 { void foo() { i = 0; }}
3627         static assert(FieldNames!S0.length == 0);
3628         static assert(__traits(isNested, S0));
3629 
3630         struct S1 { int a; void foo() { i = 0; } }
3631         static assert(FieldNames!S1 == AliasSeq!"a");
3632         static assert(__traits(isNested, S1));
3633 
3634         struct S2 { int a; string b; void foo() { i = 0; } }
3635         static assert(FieldNames!S2 == AliasSeq!("a", "b"));
3636         static assert(__traits(isNested, S2));
3637 
3638         struct S3 { int a; string b; real c; void foo() { i = 0; } }
3639         static assert(FieldNames!S3 == AliasSeq!("a", "b", "c"));
3640         static assert(__traits(isNested, S3));
3641     }
3642     {
3643         static class C0 {}
3644         static assert(FieldNames!C0.length == 0);
3645 
3646         static class C1 { int a; }
3647         static assert(FieldNames!C1 == AliasSeq!"a");
3648 
3649         static class C2 { int a; string b; }
3650         static assert(FieldNames!C2 == AliasSeq!("a", "b"));
3651 
3652         static class C3 { int a; string b; real c; }
3653         static assert(FieldNames!C3 == AliasSeq!("a", "b", "c"));
3654 
3655         static class D0 : C3 {}
3656         static assert(FieldNames!D0.length == 0);
3657 
3658         static class D1 : C3 { bool x; }
3659         static assert(FieldNames!D1 == AliasSeq!"x");
3660 
3661         static class D2 : C3 { bool x; int* y; }
3662         static assert(FieldNames!D2 == AliasSeq!("x", "y"));
3663 
3664         static class D3 : C3 { bool x; int* y; short[] z; }
3665         static assert(FieldNames!D3 == AliasSeq!("x", "y", "z"));
3666     }
3667     {
3668         int i;
3669         class C0 { void foo() { i = 0; }}
3670         static assert(FieldNames!C0.length == 0);
3671         static assert(__traits(isNested, C0));
3672 
3673         class C1 { int a; void foo() { i = 0; } }
3674         static assert(FieldNames!C1 == AliasSeq!"a");
3675         static assert(__traits(isNested, C1));
3676 
3677         class C2 { int a; string b; void foo() { i = 0; } }
3678         static assert(FieldNames!C2 == AliasSeq!("a", "b"));
3679         static assert(__traits(isNested, C2));
3680 
3681         class C3 { int a; string b; real c; void foo() { i = 0; } }
3682         static assert(FieldNames!C3 == AliasSeq!("a", "b", "c"));
3683         static assert(__traits(isNested, C3));
3684 
3685         class D0 : C3 {}
3686         static assert(FieldNames!D0.length == 0);
3687         static assert(__traits(isNested, D0));
3688 
3689         class D1 : C3 { bool x; }
3690         static assert(FieldNames!D1 == AliasSeq!"x");
3691         static assert(__traits(isNested, D1));
3692 
3693         class D2 : C3 { bool x; int* y; }
3694         static assert(FieldNames!D2 == AliasSeq!("x", "y"));
3695         static assert(__traits(isNested, D2));
3696 
3697         class D3 : C3 { bool x; int* y; short[] z; }
3698         static assert(FieldNames!D3 == AliasSeq!("x", "y", "z"));
3699         static assert(__traits(isNested, D3));
3700     }
3701     {
3702         static union U0 {}
3703         static assert(FieldNames!U0.length == 0);
3704 
3705         static union U1 { int a; }
3706         static assert(FieldNames!U1 == AliasSeq!"a");
3707 
3708         static union U2 { int a; string b; }
3709         static assert(FieldNames!U2 == AliasSeq!("a", "b"));
3710 
3711         static union U3 { int a; string b; real c; }
3712         static assert(FieldNames!U3 == AliasSeq!("a", "b", "c"));
3713     }
3714     {
3715         static struct S
3716         {
3717             enum e = 42;
3718             static str = "foobar";
3719 
3720             string name() { return "foo"; }
3721 
3722             int[] arr;
3723 
3724             struct Inner1 { int i; }
3725 
3726             static struct Inner2 { long gnol; }
3727 
3728             union { int a; string b; }
3729 
3730             alias Foo = Inner1;
3731         }
3732 
3733         static assert(FieldNames!S == AliasSeq!("arr", "a", "b"));
3734         static assert(FieldNames!(const S) == AliasSeq!("arr", "a", "b"));
3735         static assert(FieldNames!(S.Inner1) == AliasSeq!"i");
3736         static assert(FieldNames!(S.Inner2) == AliasSeq!"gnol");
3737     }
3738 }
3739 
3740 /++
3741     Evaluates to an $(D AliasSeq) of the symbols for the member variables of an
3742     aggregate type (i.e. a struct, class, interface, or union).
3743 
3744     These are fields which take up memory space within an instance of the type
3745     (i.e. not enums / manifest constants, since they don't take up memory
3746     space, and not static member variables, since they don't take up memory
3747     space within an instance).
3748 
3749     Hidden fields (like the virtual function table pointer or the context
3750     pointer for nested types) are not included.
3751 
3752     For classes, only the direct member variables are included and not those
3753     of any base classes.
3754 
3755     For interfaces, the result of FieldSymbols is always empty, because
3756     interfaces cannot have member variables. However, because interfaces are
3757     aggregate types, they work with FieldSymbols for consistency so that code
3758     that's written to work on aggregate types doesn't have to worry about
3759     whether it's dealing with an interface.
3760 
3761     In most cases, $(D FieldSymbols!T) has the same result as $(D T.tupleof).
3762     The difference is that for nested structs with a context pointer,
3763     $(D T.tupleof) includes the context pointer, whereas $(D FieldSymbols!T)
3764     does not. For non-nested structs, and for classes, interfaces, and unions,
3765     $(D FieldSymbols!T) and $(D T.tupleof) are the same.
3766 
3767     So, for most cases, $(D T.tupleof) is sufficient and avoids instantiating
3768     an additional template, but FieldSymbols is provided so that the code that
3769     needs to avoid including context pointers in the list of fields can do so
3770     without the programmer having to figure how to do that correctly. It also
3771     provides a template that's equivalent to what $(LREF FieldNames) and
3772     $(LREF FieldTypes) do in terms of which fields it gives (the difference of
3773     course then being whether you get the symbols, names, or types for the
3774     fields), whereas the behavior for $(D tupleof) is subtly different.
3775 
3776     See_Also:
3777         $(LREF FieldNames)
3778         $(LREF FieldTypes)
3779         $(DDSUBLINK spec/struct.html, struct_instance_properties, $(D tupleof))
3780         $(DDSUBLINK spec/traits, isNested, $(D __traits(isNested, ...))).
3781         $(DDSUBLINK spec/traits, isSame, $(D __traits(isSame, ...))).
3782   +/
3783 template FieldSymbols(T)
3784 if (isAggregateType!T)
3785 {
3786     static if (is(T == struct) && __traits(isNested, T))
3787     {
3788         import phobos.sys.meta : AliasSeq;
3789         alias FieldSymbols = AliasSeq!(T.tupleof[0 .. $ - 1]);
3790     }
3791     else
3792         alias FieldSymbols = T.tupleof;
3793 }
3794 
3795 ///
3796 @safe unittest
3797 {
3798     import phobos.sys.meta : AliasSeq;
3799 
3800     struct S
3801     {
3802         int x;
3803         float y;
3804     }
3805     static assert(__traits(isSame, FieldSymbols!S, AliasSeq!(S.x, S.y)));
3806 
3807     // FieldSymbols!S and S.tupleof are the same, because S is not nested.
3808     static assert(__traits(isSame, FieldSymbols!S, S.tupleof));
3809 
3810     // Note that type qualifiers _should_ be passed on to the result, but due
3811     // to https://issues.dlang.org/show_bug.cgi?id=24516, they aren't.
3812     // FieldTypes does not have this problem, because it aliases the types
3813     // rather than the symbols, so if you need the types from the symbols, you
3814     // should use either FieldTypes or tupleof until the compiler bug has been
3815     // fixed (and if you use tupleof, you need to avoid aliasing the result
3816     // before getting the types from it).
3817     static assert(is(typeof(FieldSymbols!S[0]) == int));
3818 
3819     // These currently fail when they shouldn't:
3820     //static assert(is(typeof(FieldSymbols!(const S)[0]) == const int));
3821     //static assert(is(typeof(FieldSymbols!(shared S)[0]) == shared int));
3822 
3823     class C
3824     {
3825         // static variables are not included.
3826         static int var;
3827 
3828         // Manifest constants are not included.
3829         enum lang = "dlang";
3830 
3831         // Functions are not included, even if they're @property functions.
3832         @property int foo() { return 42; }
3833 
3834         string s;
3835         int i;
3836         int[] arr;
3837     }
3838     static assert(__traits(isSame, FieldSymbols!C, AliasSeq!(C.s, C.i, C.arr)));
3839 
3840     // FieldSymbols!C and C.tupleof have the same symbols, because they are
3841     // always the same for classes.
3842     static assert(__traits(isSame, FieldSymbols!C, C.tupleof));
3843 
3844     // Only direct member variables are included. Member variables from any base
3845     // classes are not.
3846     class D : C
3847     {
3848         real r;
3849     }
3850     static assert(__traits(isSame, FieldSymbols!D, AliasSeq!(D.r)));
3851     static assert(__traits(isSame, FieldSymbols!D, D.tupleof));
3852 
3853     // FieldSymbols will always be empty for an interface, since it's not legal
3854     // for interfaces to have member variables.
3855     interface I
3856     {
3857     }
3858     static assert(FieldSymbols!I.length == 0);
3859     static assert(I.tupleof.length == 0);
3860 
3861     union U
3862     {
3863         int i;
3864         double d;
3865         long l;
3866         S s;
3867     }
3868     static assert(__traits(isSame, FieldSymbols!U, AliasSeq!(U.i, U.d, U.l, U.s)));
3869 
3870     // FieldSymbols!C and C.tupleof have the same symbols, because they are
3871     // always the same for unions.
3872     static assert(__traits(isSame, FieldSymbols!U, U.tupleof));
3873 
3874     // FieldSymbols only operates on aggregate types.
3875     static assert(!__traits(compiles, FieldSymbols!int));
3876     static assert(!__traits(compiles, FieldSymbols!(S*)));
3877     static assert(!__traits(compiles, FieldSymbols!(C[])));
3878 }
3879 
3880 /// Some examples with nested types.
3881 @safe unittest
3882 {
3883     import phobos.sys.meta : AliasSeq;
3884 
3885     int outside;
3886 
3887     struct S
3888     {
3889         long l;
3890         string s;
3891 
3892         void foo() { outside = 2; }
3893     }
3894     static assert(__traits(isNested, S));
3895     static assert(__traits(isSame, FieldSymbols!S, AliasSeq!(S.l, S.s)));
3896 
3897     // FieldSymbols!S and S.tupleof are not the same, because S is nested, and
3898     // the context pointer to the outer scope is included in S.tupleof, whereas
3899     // it is excluded from FieldSymbols!S.
3900     static assert(__traits(isSame, S.tupleof[0 .. $ - 1], AliasSeq!(S.l, S.s)));
3901     static assert(S.tupleof[$ - 1].stringof == "this");
3902 
3903     class C
3904     {
3905         bool b;
3906         int* ptr;
3907 
3908         void foo() { outside = 7; }
3909     }
3910     static assert(__traits(isNested, C));
3911     static assert(__traits(isSame, FieldSymbols!C, AliasSeq!(C.b, C.ptr)));
3912 
3913     // FieldSymbols!C and C.tupleof have the same symbols, because they are
3914     // always the same for classes. No context pointer is provided as part of
3915     // tupleof for nested classes.
3916     static assert(__traits(isSame, FieldSymbols!C, C.tupleof));
3917 
3918     // __traits(isNested, ...) is never true for interfaces or unions, since
3919     // they cannot have a context pointer to an outer scope. So, tupleof and
3920     // FieldSymbols will always be the same for interfaces and unions.
3921 }
3922 
3923 @safe unittest
3924 {
3925     import phobos.sys.meta : AliasSeq;
3926 
3927     {
3928         static struct S0 {}
3929         static assert(FieldSymbols!S0.length == 0);
3930 
3931         static struct S1 { int a; }
3932         static assert(__traits(isSame, FieldSymbols!S1, AliasSeq!(S1.a)));
3933 
3934         static struct S2 { int a; string b; }
3935         static assert(__traits(isSame, FieldSymbols!S2, AliasSeq!(S2.a, S2.b)));
3936 
3937         static struct S3 { int a; string b; real c; }
3938         static assert(__traits(isSame, FieldSymbols!S3, AliasSeq!(S3.a, S3.b, S3.c)));
3939     }
3940     {
3941         int i;
3942         struct S0 { void foo() { i = 0; }}
3943         static assert(FieldSymbols!S0.length == 0);
3944         static assert(__traits(isNested, S0));
3945 
3946         struct S1 { int a; void foo() { i = 0; } }
3947         static assert(__traits(isSame, FieldSymbols!S1, AliasSeq!(S1.a)));
3948         static assert(__traits(isNested, S1));
3949 
3950         struct S2 { int a; string b; void foo() { i = 0; } }
3951         static assert(__traits(isSame, FieldSymbols!S2, AliasSeq!(S2.a, S2.b)));
3952         static assert(__traits(isNested, S2));
3953 
3954         struct S3 { int a; string b; real c; void foo() { i = 0; } }
3955         static assert(__traits(isSame, FieldSymbols!S3, AliasSeq!(S3.a, S3.b, S3.c)));
3956         static assert(__traits(isNested, S3));
3957     }
3958     {
3959         static class C0 {}
3960         static assert(FieldSymbols!C0.length == 0);
3961 
3962         static class C1 { int a; }
3963         static assert(__traits(isSame, FieldSymbols!C1, AliasSeq!(C1.a)));
3964 
3965         static class C2 { int a; string b; }
3966         static assert(__traits(isSame, FieldSymbols!C2, AliasSeq!(C2.a, C2.b)));
3967 
3968         static class C3 { int a; string b; real c; }
3969         static assert(__traits(isSame, FieldSymbols!C3, AliasSeq!(C3.a, C3.b, C3.c)));
3970 
3971         static class D0 : C3 {}
3972         static assert(FieldSymbols!D0.length == 0);
3973 
3974         static class D1 : C3 { bool x; }
3975         static assert(__traits(isSame, FieldSymbols!D1, AliasSeq!(D1.x)));
3976 
3977         static class D2 : C3 { bool x; int* y; }
3978         static assert(__traits(isSame, FieldSymbols!D2, AliasSeq!(D2.x, D2.y)));
3979 
3980         static class D3 : C3 { bool x; int* y; short[] z; }
3981         static assert(__traits(isSame, FieldSymbols!D3, AliasSeq!(D3.x, D3.y, D3.z)));
3982     }
3983     {
3984         int i;
3985         class C0 { void foo() { i = 0; }}
3986         static assert(FieldSymbols!C0.length == 0);
3987         static assert(__traits(isNested, C0));
3988 
3989         class C1 { int a; void foo() { i = 0; } }
3990         static assert(__traits(isSame, FieldSymbols!C1, AliasSeq!(C1.a)));
3991         static assert(__traits(isNested, C1));
3992 
3993         class C2 { int a; string b; void foo() { i = 0; } }
3994         static assert(__traits(isSame, FieldSymbols!C2, AliasSeq!(C2.a, C2.b)));
3995         static assert(__traits(isNested, C2));
3996 
3997         class C3 { int a; string b; real c; void foo() { i = 0; } }
3998         static assert(__traits(isSame, FieldSymbols!C3, AliasSeq!(C3.a, C3.b, C3.c)));
3999         static assert(__traits(isNested, C3));
4000 
4001         class D0 : C3 {}
4002         static assert(FieldSymbols!D0.length == 0);
4003         static assert(__traits(isNested, D0));
4004 
4005         class D1 : C3 { bool x; }
4006         static assert(__traits(isSame, FieldSymbols!D1, AliasSeq!(D1.x)));
4007         static assert(__traits(isNested, D1));
4008 
4009         class D2 : C3 { bool x; int* y; }
4010         static assert(__traits(isSame, FieldSymbols!D2, AliasSeq!(D2.x, D2.y)));
4011         static assert(__traits(isNested, D2));
4012 
4013         class D3 : C3 { bool x; int* y; short[] z; }
4014         static assert(__traits(isSame, FieldSymbols!D3, AliasSeq!(D3.x, D3.y, D3.z)));
4015         static assert(__traits(isNested, D3));
4016     }
4017     {
4018         static union U0 {}
4019         static assert(FieldSymbols!U0.length == 0);
4020 
4021         static union U1 { int a; }
4022         static assert(__traits(isSame, FieldSymbols!U1, AliasSeq!(U1.a)));
4023 
4024         static union U2 { int a; string b; }
4025         static assert(__traits(isSame, FieldSymbols!U2, AliasSeq!(U2.a, U2.b)));
4026 
4027         static union U3 { int a; string b; real c; }
4028         static assert(__traits(isSame, FieldSymbols!U3, AliasSeq!(U3.a, U3.b, U3.c)));
4029     }
4030     {
4031         static struct S
4032         {
4033             enum e = 42;
4034             static str = "foobar";
4035 
4036             string name() { return "foo"; }
4037 
4038             int[] arr;
4039 
4040             struct Inner1 { int i; }
4041 
4042             static struct Inner2 { long gnol; }
4043 
4044             union { int a; string b; }
4045 
4046             alias Foo = Inner1;
4047         }
4048 
4049         static assert(__traits(isSame, FieldSymbols!S, AliasSeq!(S.arr, S.a, S.b)));
4050         static assert(__traits(isSame, FieldSymbols!(const S), AliasSeq!(S.arr, S.a, S.b)));
4051         static assert(__traits(isSame, FieldSymbols!(S.Inner1), AliasSeq!(S.Inner1.i)));
4052         static assert(__traits(isSame, FieldSymbols!(S.Inner2), AliasSeq!(S.Inner2.gnol)));
4053     }
4054 }
4055 
4056 /++
4057     Evaluates to an $(D AliasSeq) of the types of the member variables of an
4058     aggregate type (i.e. a struct, class, interface, or union).
4059 
4060     These are fields which take up memory space within an instance of the type
4061     (i.e. not enums / manifest constants, since they don't take up memory
4062     space, and not static member variables, since they don't take up memory
4063     space within an instance).
4064 
4065     Hidden fields (like the virtual function table pointer or the context
4066     pointer for nested types) are not included.
4067 
4068     For classes, only the direct member variables are included and not those
4069     of any base classes.
4070 
4071     For interfaces, the result of FieldTypes is always empty, because
4072     interfaces cannot have member variables. However, because interfaces are
4073     aggregate types, they work with FieldTypes for consistency so that code
4074     that's written to work on aggregate types doesn't have to worry about
4075     whether it's dealing with an interface.
4076 
4077     See_Also:
4078         $(LREF FieldNames)
4079         $(LREF FieldSymbols)
4080         $(DDSUBLINK spec/struct.html, struct_instance_properties, $(D tupleof))
4081   +/
4082 template FieldTypes(T)
4083 if (isAggregateType!T)
4084 {
4085     static if (is(T == struct) && __traits(isNested, T))
4086         alias FieldTypes = typeof(T.tupleof[0 .. $ - 1]);
4087     else
4088         alias FieldTypes = typeof(T.tupleof);
4089 }
4090 
4091 ///
4092 @safe unittest
4093 {
4094     import phobos.sys.meta : AliasSeq;
4095 
4096     struct S
4097     {
4098         int x;
4099         float y;
4100     }
4101     static assert(is(FieldTypes!S == AliasSeq!(int, float)));
4102 
4103     // Type qualifers will be passed on to the result.
4104     static assert(is(FieldTypes!(const S) == AliasSeq!(const int, const float)));
4105     static assert(is(FieldTypes!(shared S) == AliasSeq!(shared int, shared float)));
4106 
4107     class C
4108     {
4109         // static variables are not included.
4110         static int var;
4111 
4112         // Manifest constants are not included.
4113         enum lang = "dlang";
4114 
4115         // Functions are not included, even if they're @property functions.
4116         @property int foo() { return 42; }
4117 
4118         string s;
4119         int i;
4120         int[] arr;
4121     }
4122     static assert(is(FieldTypes!C == AliasSeq!(string, int, int[])));
4123 
4124     // Only direct member variables are included. Member variables from any base
4125     // classes are not.
4126     class D : C
4127     {
4128         real r;
4129     }
4130     static assert(is(FieldTypes!D == AliasSeq!real));
4131 
4132     // FieldTypes will always be empty for an interface, since it's not legal
4133     // for interfaces to have member variables.
4134     interface I
4135     {
4136     }
4137     static assert(FieldTypes!I.length == 0);
4138 
4139     union U
4140     {
4141         int i;
4142         double d;
4143         long l;
4144         S s;
4145     }
4146     static assert(is(FieldTypes!U == AliasSeq!(int, double, long, S)));
4147 
4148     // FieldTypes only operates on aggregate types.
4149     static assert(!__traits(compiles, FieldTypes!int));
4150     static assert(!__traits(compiles, FieldTypes!(S*)));
4151     static assert(!__traits(compiles, FieldTypes!(C[])));
4152 }
4153 
4154 @safe unittest
4155 {
4156     import phobos.sys.meta : AliasSeq;
4157 
4158     {
4159         static struct S0 {}
4160         static assert(FieldTypes!S0.length == 0);
4161 
4162         static struct S1 { int a; }
4163         static assert(is(FieldTypes!S1 == AliasSeq!int));
4164 
4165         static struct S2 { int a; string b; }
4166         static assert(is(FieldTypes!S2 == AliasSeq!(int, string)));
4167 
4168         static struct S3 { int a; string b; real c; }
4169         static assert(is(FieldTypes!S3 == AliasSeq!(int, string, real)));
4170     }
4171     {
4172         int i;
4173         struct S0 { void foo() { i = 0; }}
4174         static assert(FieldTypes!S0.length == 0);
4175         static assert(__traits(isNested, S0));
4176 
4177         struct S1 { int a; void foo() { i = 0; } }
4178         static assert(is(FieldTypes!S1 == AliasSeq!int));
4179         static assert(__traits(isNested, S1));
4180 
4181         struct S2 { int a; string b; void foo() { i = 0; } }
4182         static assert(is(FieldTypes!S2 == AliasSeq!(int, string)));
4183         static assert(__traits(isNested, S2));
4184 
4185         struct S3 { int a; string b; real c; void foo() { i = 0; } }
4186         static assert(is(FieldTypes!S3 == AliasSeq!(int, string, real)));
4187         static assert(__traits(isNested, S3));
4188     }
4189     {
4190         static class C0 {}
4191         static assert(FieldTypes!C0.length == 0);
4192 
4193         static class C1 { int a; }
4194         static assert(is(FieldTypes!C1 == AliasSeq!int));
4195 
4196         static class C2 { int a; string b; }
4197         static assert(is(FieldTypes!C2 == AliasSeq!(int, string)));
4198 
4199         static class C3 { int a; string b; real c; }
4200         static assert(is(FieldTypes!C3 == AliasSeq!(int, string, real)));
4201 
4202         static class D0 : C3 {}
4203         static assert(FieldTypes!D0.length == 0);
4204 
4205         static class D1 : C3 { bool x; }
4206         static assert(is(FieldTypes!D1 == AliasSeq!bool));
4207 
4208         static class D2 : C3 { bool x; int* y; }
4209         static assert(is(FieldTypes!D2 == AliasSeq!(bool, int*)));
4210 
4211         static class D3 : C3 { bool x; int* y; short[] z; }
4212         static assert(is(FieldTypes!D3 == AliasSeq!(bool, int*, short[])));
4213     }
4214     {
4215         int i;
4216         class C0 { void foo() { i = 0; }}
4217         static assert(FieldTypes!C0.length == 0);
4218         static assert(__traits(isNested, C0));
4219 
4220         class C1 { int a; void foo() { i = 0; } }
4221         static assert(is(FieldTypes!C1 == AliasSeq!int));
4222         static assert(__traits(isNested, C1));
4223 
4224         class C2 { int a; string b; void foo() { i = 0; } }
4225         static assert(is(FieldTypes!C2 == AliasSeq!(int, string)));
4226         static assert(__traits(isNested, C2));
4227 
4228         class C3 { int a; string b; real c; void foo() { i = 0; } }
4229         static assert(is(FieldTypes!C3 == AliasSeq!(int, string, real)));
4230         static assert(__traits(isNested, C3));
4231 
4232         class D0 : C3 {}
4233         static assert(FieldTypes!D0.length == 0);
4234         static assert(__traits(isNested, D0));
4235 
4236         class D1 : C3 { bool x; }
4237         static assert(is(FieldTypes!D1 == AliasSeq!bool));
4238         static assert(__traits(isNested, D1));
4239 
4240         class D2 : C3 { bool x; int* y; }
4241         static assert(is(FieldTypes!D2 == AliasSeq!(bool, int*)));
4242         static assert(__traits(isNested, D2));
4243 
4244         class D3 : C3 { bool x; int* y; short[] z; }
4245         static assert(is(FieldTypes!D3 == AliasSeq!(bool, int*, short[])));
4246         static assert(__traits(isNested, D3));
4247     }
4248     {
4249         static union U0 {}
4250         static assert(FieldTypes!U0.length == 0);
4251 
4252         static union U1 { int a; }
4253         static assert(is(FieldTypes!U1 == AliasSeq!int));
4254 
4255         static union U2 { int a; string b; }
4256         static assert(is(FieldTypes!U2 == AliasSeq!(int, string)));
4257 
4258         static union U3 { int a; string b; real c; }
4259         static assert(is(FieldTypes!U3 == AliasSeq!(int, string, real)));
4260     }
4261     {
4262         static struct S
4263         {
4264             enum e = 42;
4265             static str = "foobar";
4266 
4267             string name() { return "foo"; }
4268 
4269             int[] arr;
4270 
4271             struct Inner1 { int i; }
4272 
4273             static struct Inner2 { long gnol; }
4274 
4275             union { int a; string b; }
4276 
4277             alias Foo = Inner1;
4278         }
4279 
4280         static assert(is(FieldTypes!S == AliasSeq!(int[], int, string)));
4281         static assert(is(FieldTypes!(const S) == AliasSeq!(const(int[]), const int, const string)));
4282         static assert(is(FieldTypes!(S.Inner1) == AliasSeq!int));
4283         static assert(is(FieldTypes!(S.Inner2) == AliasSeq!long));
4284     }
4285 }
4286 
4287 /++
4288     Whether assigning to a variable of the given type involves either a
4289     user-defined $(D opAssign) or a compiler-generated $(D opAssign) rather than
4290     using the default assignment behavior (which would use $(D memcpy)). The
4291     $(D opAssign) must accept the same type (with compatible qualifiers) as the
4292     type which the $(D opAssign) is declared on for it to count for
4293     hasComplexAssignment.
4294 
4295     The compiler will generate an $(D opAssign) for a struct when a member
4296     variable of that struct defines an $(D opAssign). It will also generate one
4297     when the struct has a postblit constructor or destructor (and those can be
4298     either user-defined or compiler-generated).
4299 
4300     However, due to $(BUGZILLA 24834), the compiler does not currently generate
4301     an $(D opAssign) for structs that define a copy constructor, and so
4302     hasComplexAssignment is $(D false) for such types unless they have an
4303     explicit $(D opAssign), or the compiler generates one due to a member
4304     variable having an $(D opAssign).
4305 
4306     Note that hasComplexAssignment is also $(D true) for static arrays whose
4307     element type has an $(D opAssign), since while the static array itself does
4308     not have an $(D opAssign), the compiler must use the $(D opAssign) of the
4309     elements when assigning to the static array.
4310 
4311     Due to $(BUGZILLA 24833), enums never have complex assignment even if their
4312     base type does. Their $(D opAssign) is never called, resulting in incorrect
4313     behavior for such enums. So, because the compiler does not treat them as
4314     having complex assignment, hasComplexAssignment is $(D false) for them.
4315 
4316     No other types (including class references, pointers, and unions)
4317     ever have an $(D opAssign) and thus hasComplexAssignment is never $(D true)
4318     for them. It is particularly important to note that unions never have an
4319     $(D opAssign), so if a struct contains a union which contains one or more
4320     members which have an $(D opAssign), that struct will have to have a
4321     user-defined $(D opAssign) which explicitly assigns to the correct member
4322     of the union if you don't want the current value of the union to simply be
4323     memcopied when assigning to the struct.
4324 
4325     One big reason that code would need to worry about hasComplexAssignment is
4326     if void initialization is used anywhere. While it might be okay to assign
4327     to uninitialized memory for a type where assignment does a memcopy,
4328     assigning to uninitialized memory will cause serious issues with any
4329     $(D opAssign) which looks at the object before assigning to it (e.g.
4330     because the type uses reference counting). In such cases,
4331     $(REF copyEmplace, core, sys, lifetime) needs to be used instead of
4332     assignment.
4333 
4334     See_Also:
4335         $(LREF hasComplexCopying)
4336         $(LREF hasComplexDestruction)
4337         $(DDSUBLINK spec/operatoroverloading, assignment,
4338                     The language spec for overloading assignment)
4339         $(DDSUBLINK spec/struct, assign-overload,
4340                     The language spec for $(D opAssign) on structs)
4341   +/
4342 template hasComplexAssignment(T)
4343 {
4344     import core.internal.traits : hasElaborateAssign;
4345     alias hasComplexAssignment = hasElaborateAssign!T;
4346 }
4347 
4348 ///
4349 @safe unittest
4350 {
4351     static assert(!hasComplexAssignment!int);
4352     static assert(!hasComplexAssignment!real);
4353     static assert(!hasComplexAssignment!string);
4354     static assert(!hasComplexAssignment!(int[]));
4355     static assert(!hasComplexAssignment!(int[42]));
4356     static assert(!hasComplexAssignment!(int[string]));
4357     static assert(!hasComplexAssignment!Object);
4358 
4359     static struct NoOpAssign
4360     {
4361         int i;
4362     }
4363     static assert(!hasComplexAssignment!NoOpAssign);
4364 
4365     // For complex assignment, the parameter type must match the type of the
4366     // struct (with compatible qualifiers), but refness does not matter (though
4367     // it will obviously affect whether rvalues will be accepted as well as
4368     // whether non-copyable types will be accepted).
4369     static struct HasOpAssign
4370     {
4371         void opAssign(HasOpAssign) {}
4372     }
4373     static assert( hasComplexAssignment!HasOpAssign);
4374     static assert(!hasComplexAssignment!(const(HasOpAssign)));
4375 
4376     static struct HasOpAssignRef
4377     {
4378         void opAssign(ref HasOpAssignRef) {}
4379     }
4380     static assert( hasComplexAssignment!HasOpAssignRef);
4381     static assert(!hasComplexAssignment!(const(HasOpAssignRef)));
4382 
4383     static struct HasOpAssignAutoRef
4384     {
4385         void opAssign()(auto ref HasOpAssignAutoRef) {}
4386     }
4387     static assert( hasComplexAssignment!HasOpAssignAutoRef);
4388     static assert(!hasComplexAssignment!(const(HasOpAssignAutoRef)));
4389 
4390     // Assigning a mutable value works when opAssign takes const, because
4391     // mutable implicitly converts to const, but assigning to a const variable
4392     // does not work, so normally, a const object is not considered to have
4393     // complex assignment.
4394     static struct HasOpAssignC
4395     {
4396         void opAssign(const HasOpAssignC) {}
4397     }
4398     static assert( hasComplexAssignment!HasOpAssignC);
4399     static assert(!hasComplexAssignment!(const(HasOpAssignC)));
4400 
4401     // If opAssign is const, then assigning to a const variable will work, and a
4402     // const object will have complex assignment. However, such a type would
4403     // not normally make sense, since it can't actually be mutated by opAssign.
4404     static struct HasConstOpAssignC
4405     {
4406         void opAssign(const HasConstOpAssignC) const {}
4407     }
4408     static assert( hasComplexAssignment!HasConstOpAssignC);
4409     static assert( hasComplexAssignment!(const(HasConstOpAssignC)));
4410 
4411     // For a type to have complex assignment, the types must match aside from
4412     // the qualifiers. So, an opAssign which takes another type does not count
4413     // as complex assignment.
4414     static struct OtherOpAssign
4415     {
4416         void opAssign(int) {}
4417     }
4418     static assert(!hasComplexAssignment!OtherOpAssign);
4419 
4420     // The return type doesn't matter for complex assignment, though normally,
4421     // opAssign should either return a reference to the this reference (so that
4422     // assignments can be chained) or void.
4423     static struct HasOpAssignWeirdRet
4424     {
4425         int opAssign(HasOpAssignWeirdRet) { return 42; }
4426     }
4427     static assert( hasComplexAssignment!HasOpAssignWeirdRet);
4428 
4429     // The compiler will generate an assignment operator if a member variable
4430     // has one.
4431     static struct HasMemberWithOpAssign
4432     {
4433         HasOpAssign s;
4434     }
4435     static assert( hasComplexAssignment!HasMemberWithOpAssign);
4436 
4437     // The compiler will generate an assignment operator if the type has a
4438     // postblit constructor or a destructor.
4439     static struct HasDtor
4440     {
4441         ~this() {}
4442     }
4443     static assert( hasComplexAssignment!HasDtor);
4444 
4445     // If a struct has @disabled opAssign (and thus assigning to a variable of
4446     // that type will result in a compilation error), then
4447     // hasComplexAssignment is false.
4448     // Code that wants to check whether assignment works will need to test that
4449     // assigning to a variable of that type compiles (which could need to test
4450     // both an lvalue and an rvalue depending on the exact sort of assignment
4451     // the code is actually going to do).
4452     static struct DisabledOpAssign
4453     {
4454         @disable void opAssign(DisabledOpAssign);
4455     }
4456     static assert(!hasComplexAssignment!DisabledOpAssign);
4457     static assert(!__traits(compiles, { DisabledOpAssign s;
4458                                         s = rvalueOf!DisabledOpAssign;
4459                                         s = lvalueOf!DisabledOpAssign; }));
4460     static assert(!is(typeof({ DisabledOpAssign s;
4461                                s = rvalueOf!DisabledOpAssign;
4462                                s = lvalueOf!DisabledOpAssign; })));
4463 
4464     // Static arrays have complex assignment if their elements do.
4465     static assert( hasComplexAssignment!(HasOpAssign[1]));
4466 
4467     // Static arrays with no elements do not have complex assignment, because
4468     // there's nothing to assign to.
4469     static assert(!hasComplexAssignment!(HasOpAssign[0]));
4470 
4471     // Dynamic arrays do not have complex assignment, because assigning to them
4472     // just slices them rather than assigning to their elements. Assigning to
4473     // an array with a slice operation - e.g. arr[0 .. 5] = other[0 .. 5]; -
4474     // does use opAssign if the elements have it, but since assigning to the
4475     // array itself does not, hasComplexAssignment is false for dynamic arrays.
4476     static assert(!hasComplexAssignment!(HasOpAssign[]));
4477 
4478     // Classes and unions do not have complex assignment even if they have
4479     // members which do.
4480     class C
4481     {
4482         HasOpAssign s;
4483     }
4484     static assert(!hasComplexAssignment!C);
4485 
4486     union U
4487     {
4488         HasOpAssign s;
4489     }
4490     static assert(!hasComplexAssignment!U);
4491 
4492     // https://issues.dlang.org/show_bug.cgi?id=24833
4493     // This static assertion fails, because the compiler
4494     // currently ignores assignment operators for enum types.
4495     enum E : HasOpAssign { a = HasOpAssign.init }
4496     //static assert( hasComplexAssignment!E);
4497 }
4498 
4499 @safe unittest
4500 {
4501     import phobos.sys.meta : AliasSeq;
4502 
4503     {
4504         struct S1 { int i; }
4505         struct S2 { real r; }
4506         struct S3 { string s; }
4507         struct S4 { int[] arr; }
4508         struct S5 { int[0] arr; }
4509         struct S6 { int[42] arr; }
4510         struct S7 { int[string] aa; }
4511 
4512         static foreach (T; AliasSeq!(S1, S2, S3, S4, S5, S6, S7))
4513         {
4514             static assert(!hasComplexAssignment!T);
4515             static assert(!hasComplexAssignment!(T[0]));
4516             static assert(!hasComplexAssignment!(T[42]));
4517             static assert(!hasComplexAssignment!(T[]));
4518         }
4519     }
4520 
4521     // Basic variations of opAssign.
4522     {
4523         static struct S { void opAssign(S) {} }
4524         static assert( hasComplexAssignment!S);
4525 
4526         static struct S2 { S s; }
4527         static assert( hasComplexAssignment!S2);
4528     }
4529     {
4530         static struct S { void opAssign(ref S) {} }
4531         static assert( hasComplexAssignment!S);
4532 
4533         static struct S2 { S s; }
4534         static assert( hasComplexAssignment!S2);
4535     }
4536     {
4537         static struct S { void opAssign()(auto ref S) {} }
4538         static assert( hasComplexAssignment!S);
4539 
4540         static struct S2 { S s; }
4541         static assert( hasComplexAssignment!S2);
4542     }
4543     {
4544         static struct S { ref opAssign(S) { return this; } }
4545         static assert( hasComplexAssignment!S);
4546 
4547         static struct S2 { S s; }
4548         static assert( hasComplexAssignment!S2);
4549     }
4550     {
4551         static struct S { ref opAssign(ref S) { return this; } }
4552         static assert( hasComplexAssignment!S);
4553 
4554         static struct S2 { S s; }
4555         static assert( hasComplexAssignment!S2);
4556     }
4557     {
4558         static struct S { ref opAssign()(auto ref S) { return this; } }
4559         static assert( hasComplexAssignment!S);
4560 
4561         static struct S2 { S s; }
4562         static assert( hasComplexAssignment!S2);
4563     }
4564     {
4565         static struct S { ref opAssign(T)(auto ref T) { return this; } }
4566         static assert( hasComplexAssignment!S);
4567 
4568         static struct S2 { S s; }
4569         static assert( hasComplexAssignment!S2);
4570     }
4571 
4572     // Non-complex opAssign.
4573     {
4574         static struct S { ref opAssign(int) { return this; } }
4575         static assert(!hasComplexAssignment!S);
4576 
4577         static struct S2 { S s; }
4578         static assert(!hasComplexAssignment!S2);
4579     }
4580     {
4581         struct Other {}
4582         static struct S { ref opAssign(Other) { return this; } }
4583         static assert(!hasComplexAssignment!S);
4584 
4585         static struct S2 { S s; }
4586         static assert(!hasComplexAssignment!S2);
4587     }
4588 
4589     // Multiple opAssigns.
4590     {
4591         static struct S
4592         {
4593             void opAssign(S) {}
4594             void opAssign(int) {}
4595         }
4596         static assert( hasComplexAssignment!S);
4597 
4598         static struct S2 { S s; }
4599         static assert( hasComplexAssignment!S2);
4600     }
4601     {
4602         // This just flips the order of the previous test to catch potential
4603         // bugs related to the order of declaration, since that's occasionally
4604         // popped up in the compiler in other contexts.
4605         static struct S
4606         {
4607             void opAssign(int) {}
4608             void opAssign(S) {}
4609         }
4610         static assert( hasComplexAssignment!S);
4611 
4612         static struct S2 { S s; }
4613         static assert( hasComplexAssignment!S2);
4614     }
4615     {
4616         static struct S
4617         {
4618             void opAssign(S) {}
4619             void opAssign(ref S) {}
4620             void opAssign(const ref S) {}
4621         }
4622         static assert( hasComplexAssignment!S);
4623 
4624         static struct S2 { S s; }
4625         static assert( hasComplexAssignment!S2);
4626     }
4627 
4628     // Make sure that @disabled alternate opAssigns don't cause issues.
4629     {
4630         static struct S
4631         {
4632             void opAssign(S) {}
4633             @disable void opAssign(ref S) {}
4634         }
4635         static assert( hasComplexAssignment!S);
4636 
4637         // See https://issues.dlang.org/show_bug.cgi?id=24854
4638         // The compiler won't generate any opAssign (even if it theoretically
4639         // can) if the member variable has an @disabled opAssign which counts as
4640         // complex assignment.
4641         static struct S2 { S s; }
4642         static assert(!hasComplexAssignment!S2);
4643     }
4644     {
4645         static struct S
4646         {
4647             void opAssign(T)(T) {}
4648             @disable void opAssign(T)(ref T) {}
4649         }
4650         static assert( hasComplexAssignment!S);
4651 
4652         static struct S2 { S s; }
4653         static assert(!hasComplexAssignment!S2);
4654     }
4655     {
4656         static struct S
4657         {
4658             @disable void opAssign(S) {}
4659             void opAssign(ref S) {}
4660         }
4661         static assert( hasComplexAssignment!S);
4662 
4663         static struct S2 { S s; }
4664         static assert(!hasComplexAssignment!S2);
4665     }
4666     {
4667         static struct S
4668         {
4669             @disable void opAssign(T)(T) {}
4670             void opAssign(T)(ref T) {}
4671         }
4672         static assert( hasComplexAssignment!S);
4673 
4674         static struct S2 { S s; }
4675         static assert(!hasComplexAssignment!S2);
4676     }
4677     {
4678         static struct S
4679         {
4680             void opAssign(S) {}
4681             @disable void opAssign(int) {}
4682         }
4683         static assert( hasComplexAssignment!S);
4684 
4685         static struct S2 { S s; }
4686         static assert( hasComplexAssignment!S2);
4687     }
4688     {
4689         // The same as the previous test but in reverse order just to catch
4690         // compiler bugs related to the order of declaration.
4691         static struct S
4692         {
4693             @disable void opAssign(int) {}
4694             void opAssign(S) {}
4695         }
4696         static assert( hasComplexAssignment!S);
4697 
4698         static struct S2 { S s; }
4699         static assert( hasComplexAssignment!S2);
4700     }
4701 
4702     // Generated opAssign due to other functions.
4703     {
4704         static struct S { this(this) {} }
4705         static assert( hasComplexAssignment!S);
4706 
4707         static struct S2 { S s; }
4708         static assert( hasComplexAssignment!S2);
4709     }
4710     // https://issues.dlang.org/show_bug.cgi?id=24834
4711     /+
4712     {
4713         static struct S { this(ref S) {} }
4714         static assert( hasComplexAssignment!S);
4715 
4716         static struct S2 { S s; }
4717         static assert( hasComplexAssignment!S2);
4718     }
4719     +/
4720     {
4721         static struct S { ~this() {}  }
4722         static assert( hasComplexAssignment!S);
4723 
4724         static struct S2 { S s; }
4725         static assert( hasComplexAssignment!S2);
4726     }
4727 
4728     {
4729         static struct S
4730         {
4731             this(this) {}
4732             @disable void opAssign()(auto ref S) {}
4733         }
4734         static assert(!hasComplexAssignment!S);
4735 
4736         static struct S2 { S s; }
4737         static assert(!hasComplexAssignment!S2);
4738     }
4739     {
4740         static struct S
4741         {
4742             this(this) {}
4743             void opAssign()(auto ref S) {}
4744             @disable void opAssign(int) {}
4745         }
4746         static assert( hasComplexAssignment!S);
4747 
4748         static struct S2 { S s; }
4749         static assert( hasComplexAssignment!S2);
4750     }
4751 
4752     // Static arrays
4753     {
4754         static struct S { void opAssign(S) {} }
4755         static assert( hasComplexAssignment!S);
4756 
4757         static assert(!hasComplexAssignment!(S[0]));
4758         static assert( hasComplexAssignment!(S[12]));
4759         static assert(!hasComplexAssignment!(S[]));
4760 
4761         static struct S2 { S[42] s; }
4762         static assert( hasComplexAssignment!S2);
4763     }
4764 }
4765 
4766 /++
4767     Whether copying an object of the given type involves either a user-defined
4768     copy / postblit constructor or a compiler-generated copy / postblit
4769     constructor rather than using the default copying behavior (which would use
4770     $(D memcpy)).
4771 
4772     The compiler will generate a copy / postblit constructor for a struct when
4773     a member variable of that struct defines a copy / postblit constructor.
4774 
4775     Note that hasComplexCopying is also $(D true) for static arrays whose
4776     element type has a copy constructor or postblit constructor, since while
4777     the static array itself does not have a copy constructor or postblit
4778     constructor, the compiler must use the copy / postblit constructor of the
4779     elements when copying the static array.
4780 
4781     Due to $(BUGZILLA 24833), enums never have complex copying even if their
4782     base type does. Their copy / postblit constructor is never called,
4783     resulting in incorrect behavior for such enums. So, because the compiler
4784     does not treat them as having complex copying, hasComplexCopying is
4785     $(D false) for them.
4786 
4787     No other types (including class references, pointers, and unions) ever have
4788     a copy constructor or postblit constructor and thus hasComplexCopying is
4789     never $(D true) for them. It is particularly important to note that unions
4790     never have a copy constructor or postblit constructor, so if a struct
4791     contains a union which contains one or more members which have a copy
4792     constructor or postblit constructor, that struct will have to have a
4793     user-defined copy constructor or posthblit constructor which explicitly
4794     copies the correct member of the union if you don't want the current value
4795     of the union to simply be memcopied when copying the struct.
4796 
4797     If a particular piece of code cares about the existence of a copy
4798     constructor or postblit constructor specifically rather than if a type has
4799     one or the other, the traits
4800     $(DDSUBLINK spec/traits, hasCopyConstructor, $(D __traits(hasCopyConstructor, T)))
4801     and
4802     $(DDSUBLINK spec/traits, hasPostblit, $(D __traits(hasPostblit, T))) can
4803     be used, though note that they will not be true for static arrays.
4804 
4805     See_Also:
4806         $(LREF hasComplexAssignment)
4807         $(LREF hasComplexDestruction)
4808         $(DDSUBLINK spec/traits, hasCopyConstructor, $(D __traits(hasCopyConstructor, T)))
4809         $(DDSUBLINK spec/traits, hasPostblit, $(D __traits(hasPostblit, T)))
4810         $(DDSUBLINK spec/traits, isCopyable, $(D __traits(isCopyable, T)))
4811         $(DDSUBLINK spec/structs, struct-copy-constructor, The language spec for copy constructors)
4812         $(DDSUBLINK spec/structs, struct-postblit, The language spec for postblit constructors)
4813   +/
4814 template hasComplexCopying(T)
4815 {
4816     import core.internal.traits : hasElaborateCopyConstructor;
4817     alias hasComplexCopying = hasElaborateCopyConstructor!T;
4818 }
4819 
4820 ///
4821 @safe unittest
4822 {
4823     static assert(!hasComplexCopying!int);
4824     static assert(!hasComplexCopying!real);
4825     static assert(!hasComplexCopying!string);
4826     static assert(!hasComplexCopying!(int[]));
4827     static assert(!hasComplexCopying!(int[42]));
4828     static assert(!hasComplexCopying!(int[string]));
4829     static assert(!hasComplexCopying!Object);
4830 
4831     static struct NoCopyCtor1
4832     {
4833         int i;
4834     }
4835     static assert(!hasComplexCopying!NoCopyCtor1);
4836     static assert(!__traits(hasCopyConstructor, NoCopyCtor1));
4837     static assert(!__traits(hasPostblit, NoCopyCtor1));
4838 
4839     static struct NoCopyCtor2
4840     {
4841         int i;
4842 
4843         this(int i)
4844         {
4845             this.i = i;
4846         }
4847     }
4848     static assert(!hasComplexCopying!NoCopyCtor2);
4849     static assert(!__traits(hasCopyConstructor, NoCopyCtor2));
4850     static assert(!__traits(hasPostblit, NoCopyCtor2));
4851 
4852     struct HasCopyCtor
4853     {
4854         this(ref HasCopyCtor)
4855         {
4856         }
4857     }
4858     static assert( hasComplexCopying!HasCopyCtor);
4859     static assert( __traits(hasCopyConstructor, HasCopyCtor));
4860     static assert(!__traits(hasPostblit, HasCopyCtor));
4861 
4862     // hasComplexCopying does not take constness into account.
4863     // Code that wants to check whether copying works will need to test
4864     // __traits(isCopyable, T) or test that copying compiles.
4865     static assert( hasComplexCopying!(const HasCopyCtor));
4866     static assert( __traits(hasCopyConstructor, const HasCopyCtor));
4867     static assert(!__traits(hasPostblit, const HasCopyCtor));
4868     static assert(!__traits(isCopyable, const HasCopyCtor));
4869     static assert(!__traits(compiles, { const HasCopyCtor h;
4870                                         auto h2 = h; }));
4871     static assert(!is(typeof({ const HasCopyCtor h1;
4872                                auto h2 = h1; })));
4873 
4874     // An rvalue constructor is not a copy constructor.
4875     struct HasRValueCtor
4876     {
4877         this(HasRValueCtor)
4878         {
4879         }
4880     }
4881     static assert(!hasComplexCopying!HasRValueCtor);
4882     static assert(!__traits(hasCopyConstructor, HasRValueCtor));
4883     static assert(!__traits(hasPostblit, HasRValueCtor));
4884 
4885     struct HasPostblit
4886     {
4887         this(this)
4888         {
4889         }
4890     }
4891     static assert( hasComplexCopying!HasPostblit);
4892     static assert(!__traits(hasCopyConstructor, HasPostblit));
4893     static assert( __traits(hasPostblit, HasPostblit));
4894 
4895     // The compiler will generate a copy constructor if a member variable
4896     // has one.
4897     static struct HasMemberWithCopyCtor
4898     {
4899         HasCopyCtor s;
4900     }
4901     static assert( hasComplexCopying!HasMemberWithCopyCtor);
4902 
4903     // The compiler will generate a postblit constructor if a member variable
4904     // has one.
4905     static struct HasMemberWithPostblit
4906     {
4907         HasPostblit s;
4908     }
4909     static assert( hasComplexCopying!HasMemberWithPostblit);
4910 
4911     // If a struct has @disabled copying, hasComplexCopying is still true.
4912     // Code that wants to check whether copying works will need to test
4913     // __traits(isCopyable, T) or test that copying compiles.
4914     static struct DisabledCopying
4915     {
4916         @disable this(this);
4917         @disable this(ref DisabledCopying);
4918     }
4919     static assert( hasComplexCopying!DisabledCopying);
4920     static assert(!__traits(isCopyable, DisabledCopying));
4921     static assert(!__traits(compiles, { DisabledCopying dc1;
4922                                         auto dc2 = dc1; }));
4923     static assert(!is(typeof({ DisabledCopying dc1;
4924                                auto dc2 = dc1; })));
4925 
4926     // Static arrays have complex copying if their elements do.
4927     static assert( hasComplexCopying!(HasCopyCtor[1]));
4928     static assert( hasComplexCopying!(HasPostblit[1]));
4929 
4930     // Static arrays with no elements do not have complex copying, because
4931     // there's nothing to copy.
4932     static assert(!hasComplexCopying!(HasCopyCtor[0]));
4933     static assert(!hasComplexCopying!(HasPostblit[0]));
4934 
4935     // Dynamic arrays do not have complex copying, because copying them
4936     // just slices them rather than copying their elements.
4937     static assert(!hasComplexCopying!(HasCopyCtor[]));
4938     static assert(!hasComplexCopying!(HasPostblit[]));
4939 
4940     // Classes and unions do not have complex copying even if they have
4941     // members which do.
4942     class C
4943     {
4944         HasCopyCtor s;
4945     }
4946     static assert(!hasComplexCopying!C);
4947 
4948     union U
4949     {
4950         HasCopyCtor s;
4951     }
4952     static assert(!hasComplexCopying!U);
4953 
4954     // https://issues.dlang.org/show_bug.cgi?id=24833
4955     // This static assertion fails, because the compiler
4956     // currently ignores assignment operators for enum types.
4957     enum E : HasCopyCtor { a = HasCopyCtor.init }
4958     //static assert( hasComplexCopying!E);
4959 }
4960 
4961 @safe unittest
4962 {
4963     import phobos.sys.meta : AliasSeq;
4964 
4965     {
4966         struct S1 { int i; }
4967         struct S2 { real r; }
4968         struct S3 { string s; }
4969         struct S4 { int[] arr; }
4970         struct S5 { int[0] arr; }
4971         struct S6 { int[42] arr; }
4972         struct S7 { int[string] aa; }
4973 
4974         static foreach (T; AliasSeq!(S1, S2, S3, S4, S5, S6, S7))
4975         {
4976             static assert(!hasComplexCopying!T);
4977             static assert(!hasComplexCopying!(T[0]));
4978             static assert(!hasComplexCopying!(T[42]));
4979             static assert(!hasComplexCopying!(T[]));
4980         }
4981     }
4982 
4983     // Basic variations of copy constructors.
4984     {
4985         static struct S { this(ref S) {} }
4986         static assert( hasComplexCopying!S);
4987 
4988         static struct S2 { S s; }
4989         static assert( hasComplexCopying!S2);
4990     }
4991     {
4992         static struct S { this(const ref S) const {} }
4993         static assert( hasComplexCopying!S);
4994 
4995         static struct S2 { S s; }
4996         static assert( hasComplexCopying!S2);
4997     }
4998     {
4999         static struct S
5000         {
5001             this(ref S) {}
5002             this(const ref S) const {}
5003         }
5004         static assert( hasComplexCopying!S);
5005 
5006         static struct S2 { S s; }
5007         static assert( hasComplexCopying!S2);
5008     }
5009     {
5010         static struct S { this(inout ref S) inout {} }
5011         static assert( hasComplexCopying!S);
5012 
5013         static struct S2 { S s; }
5014         static assert( hasComplexCopying!S2);
5015     }
5016     {
5017         static struct S { this(scope ref S) {} }
5018         static assert( hasComplexCopying!S);
5019 
5020         static struct S2 { S s; }
5021         static assert( hasComplexCopying!S2);
5022     }
5023     {
5024         static struct S { this(scope ref S) scope {} }
5025         static assert( hasComplexCopying!S);
5026 
5027         static struct S2 { S s; }
5028         static assert( hasComplexCopying!S2);
5029     }
5030     {
5031         static struct S { this(ref S) @safe {} }
5032         static assert( hasComplexCopying!S);
5033 
5034         static struct S2 { S s; }
5035         static assert( hasComplexCopying!S2);
5036     }
5037     {
5038         static struct S { this(ref S) nothrow {} }
5039         static assert( hasComplexCopying!S);
5040 
5041         static struct S2 { S s; }
5042         static assert( hasComplexCopying!S2);
5043     }
5044     {
5045         static struct S { this(scope inout ref S) inout scope @safe pure nothrow @nogc {} }
5046         static assert( hasComplexCopying!S);
5047 
5048         static struct S2 { S s; }
5049         static assert( hasComplexCopying!S2);
5050     }
5051 
5052     // Basic variations of postblit constructors.
5053     {
5054         static struct S { this(this) {} }
5055         static assert( hasComplexCopying!S);
5056 
5057         static struct S2 { S s; }
5058         static assert( hasComplexCopying!S2);
5059     }
5060     {
5061         static struct S { this(this) scope @safe pure nothrow @nogc {} }
5062         static assert( hasComplexCopying!S);
5063 
5064         static struct S2 { S s; }
5065         static assert( hasComplexCopying!S2);
5066     }
5067 
5068     // Rvalue constructors.
5069     {
5070         static struct S { this(S) {} }
5071         static assert(!hasComplexCopying!S);
5072 
5073         static struct S2 { S s; }
5074         static assert(!hasComplexCopying!S2);
5075     }
5076     {
5077         static struct S { this(const S) const {} }
5078         static assert(!hasComplexCopying!S);
5079 
5080         static struct S2 { S s; }
5081         static assert(!hasComplexCopying!S2);
5082     }
5083     {
5084         static struct S
5085         {
5086             this(S) {}
5087             this(const S) const {}
5088         }
5089         static assert(!hasComplexCopying!S);
5090 
5091         static struct S2 { S s; }
5092         static assert(!hasComplexCopying!S2);
5093     }
5094     {
5095         static struct S { this(inout S) inout {} }
5096         static assert(!hasComplexCopying!S);
5097 
5098         static struct S2 { S s; }
5099         static assert(!hasComplexCopying!S2);
5100     }
5101     {
5102         static struct S { this(S) @safe {} }
5103         static assert(!hasComplexCopying!S);
5104 
5105         static struct S2 { S s; }
5106         static assert(!hasComplexCopying!S2);
5107     }
5108     {
5109         static struct S { this(S) nothrow {} }
5110         static assert(!hasComplexCopying!S);
5111 
5112         static struct S2 { S s; }
5113         static assert(!hasComplexCopying!S2);
5114     }
5115     {
5116         static struct S { this(inout S) inout @safe pure nothrow @nogc {} }
5117         static assert(!hasComplexCopying!S);
5118 
5119         static struct S2 { S s; }
5120         static assert(!hasComplexCopying!S2);
5121     }
5122 
5123     // @disabled copy constructors.
5124     {
5125         static struct S { @disable this(ref S) {} }
5126         static assert( hasComplexCopying!S);
5127 
5128         static struct S2 { S s; }
5129         static assert( hasComplexCopying!S2);
5130     }
5131     {
5132         static struct S { @disable this(const ref S) const {} }
5133         static assert( hasComplexCopying!S);
5134 
5135         static struct S2 { S s; }
5136         static assert( hasComplexCopying!S2);
5137     }
5138     {
5139         static struct S
5140         {
5141             @disable this(ref S) {}
5142             this(const ref S) const {}
5143         }
5144         static assert( hasComplexCopying!S);
5145 
5146         static struct S2 { S s; }
5147         static assert( hasComplexCopying!S2);
5148     }
5149     {
5150         static struct S
5151         {
5152             this(ref S) {}
5153             @disable this(const ref S) const {}
5154         }
5155         static assert( hasComplexCopying!S);
5156 
5157         static struct S2 { S s; }
5158         static assert( hasComplexCopying!S2);
5159     }
5160     {
5161         static struct S
5162         {
5163             @disable this(ref S) {}
5164             @disable this(const ref S) const {}
5165         }
5166         static assert( hasComplexCopying!S);
5167 
5168         static struct S2 { S s; }
5169         static assert( hasComplexCopying!S2);
5170     }
5171 
5172     // Static arrays
5173     {
5174         static struct S { this(ref S) {} }
5175         static assert( hasComplexCopying!S);
5176 
5177         static assert(!hasComplexCopying!(S[0]));
5178         static assert( hasComplexCopying!(S[12]));
5179         static assert(!hasComplexCopying!(S[]));
5180 
5181         static struct S2 { S[42] s; }
5182         static assert( hasComplexCopying!S2);
5183     }
5184     {
5185         static struct S { this(this) {} }
5186         static assert( hasComplexCopying!S);
5187 
5188         static assert(!hasComplexCopying!(S[0]));
5189         static assert( hasComplexCopying!(S[12]));
5190         static assert(!hasComplexCopying!(S[]));
5191 
5192         static struct S2 { S[42] s; }
5193         static assert( hasComplexCopying!S2);
5194     }
5195 }
5196 
5197 /++
5198     Whether the given type has either a user-defined destructor or a
5199     compiler-generated destructor.
5200 
5201     The compiler will generate a destructor for a struct when a member variable
5202     of that struct defines a destructor.
5203 
5204     Note that hasComplexDestruction is also $(D true) for static arrays whose
5205     element type has a destructor, since while the static array itself does not
5206     have a destructor, the compiler must use the destructor of the elements
5207     when destroying the static array.
5208 
5209     Due to $(BUGZILLA 24833), enums never have complex destruction even if their
5210     base type does. Their destructor is never called, resulting in incorrect
5211     behavior for such enums. So, because the compiler does not treat them as
5212     having complex destruction, hasComplexDestruction is $(D false) for them.
5213 
5214     Note that while the $(DDSUBLINK spec/class, destructors, language spec)
5215     currently refers to $(D ~this()) on classes as destructors (whereas the
5216     runtime refers to them as finalizers, and they're arguably finalizers
5217     rather than destructors given how they work), classes are not considered to
5218     have complex destruction. Under normal circumstances, it's just the GC or
5219     $(REF1 destroy, object) which calls the destructor / finalizer on a class
5220     (and it's not guaranteed that a class destructor / finalizer will even ever
5221     be called), which is in stark contrast to structs, which normally live on
5222     the stack and need to be destroyed when they leave scope. So,
5223     hasComplexDestruction is concerned with whether that type will have a
5224     destructor that's run when it leaves scope and not with what happens when
5225     the GC destroys an object prior to freeing its memory.
5226 
5227     No other types (including pointers and unions) ever have a destructor and
5228     thus hasComplexDestruction is never $(D true) for them. It is particularly
5229     important to note that unions never have a destructor, so if a struct
5230     contains a union which contains one or more members which have a
5231     destructor, that struct will have to have a user-defined destructor which
5232     explicitly calls $(REF1 destroy, object) on the correct member of the
5233     union if you want the object in question to be destroyed properly.
5234 
5235     See_Also:
5236         $(LREF hasComplexAssignment)
5237         $(LREF hasComplexCopying)
5238         $(REF destroy, object)
5239         $(DDSUBLINK spec/structs, struct-destructor, The language spec for destructors)
5240         $(DDSUBLINK spec/class, destructors, The language spec for class finalizers)
5241   +/
5242 template hasComplexDestruction(T)
5243 {
5244     import core.internal.traits : hasElaborateDestructor;
5245     alias hasComplexDestruction = hasElaborateDestructor!T;
5246 }
5247 
5248 ///
5249 @safe unittest
5250 {
5251     static assert(!hasComplexDestruction!int);
5252     static assert(!hasComplexDestruction!real);
5253     static assert(!hasComplexDestruction!string);
5254     static assert(!hasComplexDestruction!(int[]));
5255     static assert(!hasComplexDestruction!(int[42]));
5256     static assert(!hasComplexDestruction!(int[string]));
5257     static assert(!hasComplexDestruction!Object);
5258 
5259     static struct NoDtor
5260     {
5261         int i;
5262     }
5263     static assert(!hasComplexDestruction!NoDtor);
5264 
5265     struct HasDtor
5266     {
5267         ~this() {}
5268     }
5269     static assert( hasComplexDestruction!HasDtor);
5270 
5271     // The compiler will generate a destructor if a member variable has one.
5272     static struct HasMemberWithDtor
5273     {
5274         HasDtor s;
5275     }
5276     static assert( hasComplexDestruction!HasMemberWithDtor);
5277 
5278     // If a struct has @disabled destruction, hasComplexDestruction is still
5279     // true. Code that wants to check whether destruction works can either
5280     // test for whether the __xdtor member is disabled, or it can test whether
5281     // code that will destroy the object compiles. That being said, a disabled
5282     // destructor probably isn't very common in practice, because about all that
5283     // such a type is good for is being allocated on the heap.
5284     static struct DisabledDtor
5285     {
5286         @disable ~this() {}
5287     }
5288     static assert( hasComplexDestruction!DisabledDtor);
5289     static assert( __traits(isDisabled,
5290                             __traits(getMember, DisabledDtor, "__xdtor")));
5291 
5292     // A type with a disabled destructor cannot be created on the stack or used
5293     // in any way that would ever trigger a destructor, making it pretty much
5294     // useless outside of providing a way to force a struct to be allocated on
5295     // the heap - though that could be useful in some situations, since it
5296     // it makes it possible to have a type that has to be a reference type but
5297     // which doesn't have the overhead of a class.
5298     static assert(!__traits(compiles, { DisabledDtor d; }));
5299     static assert( __traits(compiles, { auto d = new DisabledDtor; }));
5300 
5301     // Static arrays have complex destruction if their elements do.
5302     static assert( hasComplexDestruction!(HasDtor[1]));
5303 
5304     // Static arrays with no elements do not have complex destruction, because
5305     // there's nothing to destroy.
5306     static assert(!hasComplexDestruction!(HasDtor[0]));
5307 
5308     // Dynamic arrays do not have complex destruction, because their elements
5309     // are contained in the memory that the dynamic array is a slice of and not
5310     // in the dynamic array itself, so there's nothing to destroy when a
5311     // dynamic array leaves scope.
5312     static assert(!hasComplexDestruction!(HasDtor[]));
5313 
5314     // Classes and unions do not have complex copying even if they have
5315     // members which do.
5316     class C
5317     {
5318         HasDtor s;
5319     }
5320     static assert(!hasComplexDestruction!C);
5321 
5322     union U
5323     {
5324         HasDtor s;
5325     }
5326     static assert(!hasComplexDestruction!U);
5327 
5328     // https://issues.dlang.org/show_bug.cgi?id=24833
5329     // This static assertion fails, because the compiler
5330     // currently ignores assignment operators for enum types.
5331     enum E : HasDtor { a = HasDtor.init }
5332     //static assert( hasComplexDestruction!E);
5333 }
5334 
5335 @safe unittest
5336 {
5337     import phobos.sys.meta : AliasSeq;
5338 
5339     {
5340         struct S1 { int i; }
5341         struct S2 { real r; }
5342         struct S3 { string s; }
5343         struct S4 { int[] arr; }
5344         struct S5 { int[0] arr; }
5345         struct S6 { int[42] arr; }
5346         struct S7 { int[string] aa; }
5347 
5348         static foreach (T; AliasSeq!(S1, S2, S3, S4, S5, S6, S7))
5349         {
5350             static assert(!hasComplexDestruction!T);
5351             static assert(!hasComplexDestruction!(T[0]));
5352             static assert(!hasComplexDestruction!(T[42]));
5353             static assert(!hasComplexDestruction!(T[]));
5354         }
5355     }
5356 
5357     // Basic variations of destructors.
5358     {
5359         static struct S { ~this() {} }
5360         static assert( hasComplexDestruction!S);
5361 
5362         static struct S2 { S s; }
5363         static assert( hasComplexDestruction!S2);
5364     }
5365     {
5366         static struct S { ~this() const {} }
5367         static assert( hasComplexDestruction!S);
5368 
5369         static struct S2 { S s; }
5370         static assert( hasComplexDestruction!S2);
5371     }
5372     {
5373         static struct S { ~this() @safe {} }
5374         static assert( hasComplexDestruction!S);
5375 
5376         static struct S2 { S s; }
5377         static assert( hasComplexDestruction!S2);
5378     }
5379     {
5380         static struct S { ~this() @safe pure nothrow @nogc {} }
5381         static assert( hasComplexDestruction!S);
5382 
5383         static struct S2 { S s; }
5384         static assert( hasComplexDestruction!S2);
5385     }
5386 
5387     // @disabled destructors.
5388     {
5389         static struct S { @disable ~this() {} }
5390         static assert( __traits(isDisabled,
5391                                 __traits(getMember, S, "__xdtor")));
5392 
5393         static struct S2 { S s; }
5394         static assert( hasComplexDestruction!S2);
5395         static assert( __traits(isDisabled,
5396                                 __traits(getMember, S2, "__xdtor")));
5397     }
5398 
5399     // Static arrays
5400     {
5401         static struct S { ~this() {} }
5402         static assert( hasComplexDestruction!S);
5403 
5404         static assert(!hasComplexDestruction!(S[0]));
5405         static assert( hasComplexDestruction!(S[12]));
5406         static assert(!hasComplexDestruction!(S[]));
5407 
5408         static struct S2 { S[42] s; }
5409         static assert( hasComplexDestruction!S2);
5410     }
5411 }
5412 
5413 /++
5414     Evaluates to $(D true) if the given type is one or more of the following,
5415     or if it's a struct, union, or static array which contains one or more of
5416     the following:
5417 
5418     $(OL $(LI A raw pointer)
5419          $(LI A class reference)
5420          $(LI An interface reference)
5421          $(LI A dynamic array)
5422          $(LI An associative array)
5423          $(LI A delegate)
5424          $(LI A struct with a
5425               $(DDSUBLINK spec/traits, isNested, $(D context pointer)).))
5426 
5427     Note that function pointers are not considered to have indirections, because
5428     they do not point to any data (whereas a delegate has a context pointer
5429     and therefore has data that it points to).
5430 
5431     Also, while static arrays do not have indirections unless their element
5432     type has indirections, static arrays with an element type of $(D void) are
5433     considered to have indirections by hasIndirections, because it's unknown
5434     what type their elements actually are, so they $(I might) have
5435     indirections, and thus, the conservative approach is to assume that they do
5436     have indirections.
5437 
5438     Static arrays with length 0 do not have indirections no matter what their
5439     element type is, since they don't actually have any elements.
5440   +/
5441 version (StdDdoc) template hasIndirections(T)
5442 {
5443     import core.internal.traits : _hasIndirections = hasIndirections;
5444     alias hasIndirections = _hasIndirections!T;
5445 }
5446 else
5447 {
5448     import core.internal.traits : _hasIndirections = hasIndirections;
5449     alias hasIndirections = _hasIndirections;
5450 }
5451 
5452 ///
5453 @safe unittest
5454 {
5455     static class C {}
5456     static interface I {}
5457 
5458     static assert( hasIndirections!(int*));
5459     static assert( hasIndirections!C);
5460     static assert( hasIndirections!I);
5461     static assert( hasIndirections!(int[]));
5462     static assert( hasIndirections!(int[string]));
5463     static assert( hasIndirections!(void delegate()));
5464     static assert( hasIndirections!(string delegate(int)));
5465 
5466     static assert(!hasIndirections!(void function()));
5467     static assert(!hasIndirections!int);
5468 
5469     static assert(!hasIndirections!(ubyte[9]));
5470     static assert( hasIndirections!(ubyte[9]*));
5471     static assert( hasIndirections!(ubyte*[9]));
5472     static assert(!hasIndirections!(ubyte*[0]));
5473     static assert( hasIndirections!(ubyte[]));
5474 
5475     static assert( hasIndirections!(void[]));
5476     static assert( hasIndirections!(void[42]));
5477 
5478     static struct NoContext
5479     {
5480         int i;
5481     }
5482 
5483     int local;
5484 
5485     struct HasContext
5486     {
5487         int foo() { return local; }
5488     }
5489 
5490     struct HasMembersWithIndirections
5491     {
5492         int* ptr;
5493     }
5494 
5495     static assert(!hasIndirections!NoContext);
5496     static assert( hasIndirections!HasContext);
5497     static assert( hasIndirections!HasMembersWithIndirections);
5498 
5499     union U1
5500     {
5501         int i;
5502         float f;
5503     }
5504     static assert(!hasIndirections!U1);
5505 
5506     union U2
5507     {
5508         int i;
5509         int[] arr;
5510     }
5511     static assert( hasIndirections!U2);
5512 }
5513 
5514 // hasIndirections with types which aren't aggregate types.
5515 @safe unittest
5516 {
5517     import phobos.sys.meta : AliasSeq;
5518 
5519     alias testWithQualifiers = assertWithQualifiers!hasIndirections;
5520 
5521     foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
5522                           float, double, real, char, wchar, dchar, int function(string), void))
5523     {
5524         mixin testWithQualifiers!(T, false);
5525         mixin testWithQualifiers!(T*, true);
5526         mixin testWithQualifiers!(T[], true);
5527 
5528         mixin testWithQualifiers!(T[42], is(T == void));
5529         mixin testWithQualifiers!(T[0], false);
5530 
5531         mixin testWithQualifiers!(T*[42], true);
5532         mixin testWithQualifiers!(T*[0], false);
5533 
5534         mixin testWithQualifiers!(T[][42], true);
5535         mixin testWithQualifiers!(T[][0], false);
5536     }
5537 
5538     foreach (T; AliasSeq!(int[int], int delegate(string)))
5539     {
5540         mixin testWithQualifiers!(T, true);
5541         mixin testWithQualifiers!(T*, true);
5542         mixin testWithQualifiers!(T[], true);
5543 
5544         mixin testWithQualifiers!(T[42], true);
5545         mixin testWithQualifiers!(T[0], false);
5546 
5547         mixin testWithQualifiers!(T*[42], true);
5548         mixin testWithQualifiers!(T*[0], false);
5549 
5550         mixin testWithQualifiers!(T[][42], true);
5551         mixin testWithQualifiers!(T[][0], false);
5552     }
5553 }
5554 
5555 // hasIndirections with structs.
5556 @safe unittest
5557 {
5558     import phobos.sys.meta : AliasSeq;
5559 
5560     alias testWithQualifiers = assertWithQualifiers!hasIndirections;
5561 
5562     {
5563         struct S {}
5564         mixin testWithQualifiers!(S, false);
5565     }
5566     {
5567         static struct S {}
5568         mixin testWithQualifiers!(S, false);
5569     }
5570     {
5571         struct S { void foo() {} }
5572         mixin testWithQualifiers!(S, true);
5573     }
5574     {
5575         static struct S { void foo() {} }
5576         mixin testWithQualifiers!(S, false);
5577     }
5578 
5579     // Structs with members which aren't aggregate types and don't have indirections.
5580     foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
5581                           float, double, real, char, wchar, dchar, int function(string)))
5582     {
5583         // No indirections.
5584         {
5585             struct S { T member; }
5586             mixin testWithQualifiers!(S, false);
5587         }
5588         {
5589             struct S { const T member; }
5590             mixin testWithQualifiers!(S, false);
5591         }
5592         {
5593             struct S { immutable T member; }
5594             mixin testWithQualifiers!(S, false);
5595         }
5596         {
5597             struct S { shared T member; }
5598             mixin testWithQualifiers!(S, false);
5599         }
5600 
5601         {
5602             static struct S { T member; void foo() {} }
5603             mixin testWithQualifiers!(S, false);
5604         }
5605         {
5606             static struct S { const T member; void foo() {} }
5607             mixin testWithQualifiers!(S, false);
5608         }
5609         {
5610             static struct S { immutable T member; void foo() {} }
5611             mixin testWithQualifiers!(S, false);
5612         }
5613         {
5614             static struct S { shared T member; void foo() {} }
5615             mixin testWithQualifiers!(S, false);
5616         }
5617 
5618         // Has context pointer.
5619         {
5620             struct S { T member; void foo() {} }
5621             mixin testWithQualifiers!(S, true);
5622         }
5623         {
5624             struct S { const T member; void foo() {} }
5625             mixin testWithQualifiers!(S, true);
5626         }
5627         {
5628             struct S { immutable T member; void foo() {} }
5629             mixin testWithQualifiers!(S, true);
5630         }
5631         {
5632             struct S { shared T member; void foo() {} }
5633             mixin testWithQualifiers!(S, true);
5634         }
5635 
5636         {
5637             T local;
5638             struct S { void foo() { auto v = local; } }
5639             mixin testWithQualifiers!(S, true);
5640         }
5641         {
5642             const T local;
5643             struct S { void foo() { auto v = local; } }
5644             mixin testWithQualifiers!(S, true);
5645         }
5646         {
5647             immutable T local;
5648             struct S { void foo() { auto v = local; } }
5649             mixin testWithQualifiers!(S, true);
5650         }
5651         {
5652             shared T local;
5653             struct S { void foo() @trusted { auto v = cast() local; } }
5654             mixin testWithQualifiers!(S, true);
5655         }
5656 
5657         // Pointers.
5658         {
5659             struct S { T* member; }
5660             mixin testWithQualifiers!(S, true);
5661         }
5662         {
5663             struct S { const(T)* member; }
5664             mixin testWithQualifiers!(S, true);
5665         }
5666         {
5667             struct S { const T* member; }
5668             mixin testWithQualifiers!(S, true);
5669         }
5670         {
5671             struct S { immutable T* member; }
5672             mixin testWithQualifiers!(S, true);
5673         }
5674         {
5675             struct S { shared T* member; }
5676             mixin testWithQualifiers!(S, true);
5677         }
5678 
5679         // Dynamic arrays.
5680         {
5681             struct S { T[] member; }
5682             mixin testWithQualifiers!(S, true);
5683         }
5684         {
5685             struct S { const(T)[] member; }
5686             mixin testWithQualifiers!(S, true);
5687         }
5688         {
5689             struct S { const T[] member; }
5690             mixin testWithQualifiers!(S, true);
5691         }
5692         {
5693             struct S { immutable T[] member; }
5694             mixin testWithQualifiers!(S, true);
5695         }
5696         {
5697             struct S { shared T[] member; }
5698             mixin testWithQualifiers!(S, true);
5699         }
5700 
5701         // Static arrays.
5702         {
5703             struct S { T[1] member; }
5704             mixin testWithQualifiers!(S, false);
5705         }
5706         {
5707             struct S { const(T)[1] member; }
5708             mixin testWithQualifiers!(S, false);
5709         }
5710         {
5711             struct S { const T[1] member; }
5712             mixin testWithQualifiers!(S, false);
5713         }
5714         {
5715             struct S { immutable T[1] member; }
5716             mixin testWithQualifiers!(S, false);
5717         }
5718         {
5719             struct S { shared T[1] member; }
5720             mixin testWithQualifiers!(S, false);
5721         }
5722 
5723         // Static arrays of pointers.
5724         {
5725             struct S { T*[1] member; }
5726             mixin testWithQualifiers!(S, true);
5727         }
5728         {
5729             struct S { const(T)*[1] member; }
5730             mixin testWithQualifiers!(S, true);
5731         }
5732         {
5733             struct S { const(T*)[1] member; }
5734             mixin testWithQualifiers!(S, true);
5735         }
5736         {
5737             struct S { const T*[1] member; }
5738             mixin testWithQualifiers!(S, true);
5739         }
5740         {
5741             struct S { immutable T*[1] member; }
5742             mixin testWithQualifiers!(S, true);
5743         }
5744         {
5745             struct S { shared T*[1] member; }
5746             mixin testWithQualifiers!(S, true);
5747         }
5748 
5749         {
5750             struct S { T*[0] member; }
5751             mixin testWithQualifiers!(S, false);
5752         }
5753         {
5754             struct S { const(T)*[0] member; }
5755             mixin testWithQualifiers!(S, false);
5756         }
5757         {
5758             struct S { const(T*)[0] member; }
5759             mixin testWithQualifiers!(S, false);
5760         }
5761         {
5762             struct S { const T*[0] member; }
5763             mixin testWithQualifiers!(S, false);
5764         }
5765         {
5766             struct S { immutable T*[0] member; }
5767             mixin testWithQualifiers!(S, false);
5768         }
5769         {
5770             struct S { shared T*[0] member; }
5771             mixin testWithQualifiers!(S, false);
5772         }
5773 
5774         // Static arrays of dynamic arrays.
5775         {
5776             struct S { T[][1] member; }
5777             mixin testWithQualifiers!(S, true);
5778         }
5779         {
5780             struct S { const(T)[][1] member; }
5781             mixin testWithQualifiers!(S, true);
5782         }
5783         {
5784             struct S { const(T[])[1] member; }
5785             mixin testWithQualifiers!(S, true);
5786         }
5787         {
5788             struct S { const T[][1] member; }
5789             mixin testWithQualifiers!(S, true);
5790         }
5791         {
5792             struct S { immutable T[][1] member; }
5793             mixin testWithQualifiers!(S, true);
5794         }
5795         {
5796             struct S { shared T[][1] member; }
5797             mixin testWithQualifiers!(S, true);
5798         }
5799 
5800         {
5801             struct S { T[][0] member; }
5802             mixin testWithQualifiers!(S, false);
5803         }
5804         {
5805             struct S { const(T)[][0] member; }
5806             mixin testWithQualifiers!(S, false);
5807         }
5808         {
5809             struct S { const(T[])[0] member; }
5810             mixin testWithQualifiers!(S, false);
5811         }
5812         {
5813             struct S { const T[][0] member; }
5814             mixin testWithQualifiers!(S, false);
5815         }
5816         {
5817             struct S { immutable T[][0] member; }
5818             mixin testWithQualifiers!(S, false);
5819         }
5820         {
5821             struct S { shared T[][0] member; }
5822             mixin testWithQualifiers!(S, false);
5823         }
5824     }
5825 
5826     // Structs with arrays of void.
5827     {
5828         {
5829             static struct S { void[] member; }
5830             mixin testWithQualifiers!(S, true);
5831         }
5832         {
5833             static struct S { void[1] member; }
5834             mixin testWithQualifiers!(S, true);
5835         }
5836         {
5837             static struct S { void[0] member; }
5838             mixin testWithQualifiers!(S, false);
5839         }
5840     }
5841 
5842     // Structs with multiple members, testing pointer types.
5843     {
5844         static struct S { int i; bool b; }
5845         mixin testWithQualifiers!(S, false);
5846     }
5847     {
5848         static struct S { int* i; bool b; }
5849         mixin testWithQualifiers!(S, true);
5850     }
5851     {
5852         static struct S { int i; bool* b; }
5853         mixin testWithQualifiers!(S, true);
5854     }
5855     {
5856         static struct S { int* i; bool* b; }
5857         mixin testWithQualifiers!(S, true);
5858     }
5859 
5860     // Structs with multiple members, testing dynamic arrays.
5861     {
5862         static struct S { int[] arr; }
5863         mixin testWithQualifiers!(S, true);
5864     }
5865     {
5866         static struct S { int i; int[] arr; }
5867         mixin testWithQualifiers!(S, true);
5868     }
5869     {
5870         static struct S { int[] arr; int i; }
5871         mixin testWithQualifiers!(S, true);
5872     }
5873 
5874     // Structs with multiple members, testing static arrays.
5875     {
5876         static struct S { int[1] arr; }
5877         mixin testWithQualifiers!(S, false);
5878     }
5879     {
5880         static struct S { int i; int[1] arr; }
5881         mixin testWithQualifiers!(S, false);
5882     }
5883     {
5884         static struct S { int[1] arr; int i; }
5885         mixin testWithQualifiers!(S, false);
5886     }
5887 
5888     {
5889         static struct S { int*[0] arr; }
5890         mixin testWithQualifiers!(S, false);
5891     }
5892     {
5893         static struct S { int i; int*[0] arr; }
5894         mixin testWithQualifiers!(S, false);
5895     }
5896     {
5897         static struct S { int*[0] arr; int i; }
5898         mixin testWithQualifiers!(S, false);
5899     }
5900 
5901     {
5902         static struct S { string[42] arr; }
5903         mixin testWithQualifiers!(S, true);
5904     }
5905     {
5906         static struct S { int i; string[42] arr; }
5907         mixin testWithQualifiers!(S, true);
5908     }
5909     {
5910         static struct S { string[42] arr; int i; }
5911         mixin testWithQualifiers!(S, true);
5912     }
5913 
5914     // Structs with associative arrays.
5915     {
5916         static struct S { int[string] aa; }
5917         mixin testWithQualifiers!(S, true);
5918     }
5919     {
5920         static struct S { int i; int[string] aa; }
5921         mixin testWithQualifiers!(S, true);
5922     }
5923     {
5924         static struct S { int[string] aa; int i; }
5925         mixin testWithQualifiers!(S, true);
5926     }
5927 
5928     {
5929         static struct S { int[42][int] aa; }
5930         mixin testWithQualifiers!(S, true);
5931     }
5932     {
5933         static struct S { int[0][int] aa; }
5934         mixin testWithQualifiers!(S, true);
5935     }
5936 
5937     // Structs with classes.
5938     {
5939         class C {}
5940         struct S { C c; }
5941         mixin testWithQualifiers!(S, true);
5942     }
5943     {
5944         interface I {}
5945         struct S { I i; }
5946         mixin testWithQualifiers!(S, true);
5947     }
5948 
5949     // Structs with delegates.
5950     {
5951         struct S { void delegate() d; }
5952         mixin testWithQualifiers!(S, true);
5953     }
5954     {
5955         struct S { int delegate(int) d; }
5956         mixin testWithQualifiers!(S, true);
5957     }
5958 
5959     // Structs multiple layers deep.
5960     {
5961         struct S1 { int i; }
5962         struct S2 { S1 s; }
5963         struct S3 { S2 s; }
5964         struct S4 { S3 s; }
5965         struct S5 { S4 s; }
5966         struct S6 { S5 s; }
5967         struct S7 { S6[0] s; }
5968         struct S8 { S7 s; }
5969         struct S9 { S8 s; }
5970         struct S10 { S9 s; }
5971         mixin testWithQualifiers!(S1, false);
5972         mixin testWithQualifiers!(S2, false);
5973         mixin testWithQualifiers!(S3, false);
5974         mixin testWithQualifiers!(S4, false);
5975         mixin testWithQualifiers!(S5, false);
5976         mixin testWithQualifiers!(S6, false);
5977         mixin testWithQualifiers!(S7, false);
5978         mixin testWithQualifiers!(S8, false);
5979         mixin testWithQualifiers!(S9, false);
5980         mixin testWithQualifiers!(S10, false);
5981     }
5982     {
5983         struct S1 { int* i; }
5984         struct S2 { S1 s; }
5985         struct S3 { S2 s; }
5986         struct S4 { S3 s; }
5987         struct S5 { S4 s; }
5988         struct S6 { S5 s; }
5989         struct S7 { S6[0] s; }
5990         struct S8 { S7 s; }
5991         struct S9 { S8 s; }
5992         struct S10 { S9 s; }
5993         mixin testWithQualifiers!(S1, true);
5994         mixin testWithQualifiers!(S2, true);
5995         mixin testWithQualifiers!(S3, true);
5996         mixin testWithQualifiers!(S4, true);
5997         mixin testWithQualifiers!(S5, true);
5998         mixin testWithQualifiers!(S6, true);
5999         mixin testWithQualifiers!(S7, false);
6000         mixin testWithQualifiers!(S8, false);
6001         mixin testWithQualifiers!(S9, false);
6002         mixin testWithQualifiers!(S10, false);
6003     }
6004 }
6005 
6006 // hasIndirections with unions.
6007 @safe unittest
6008 {
6009     import phobos.sys.meta : AliasSeq;
6010 
6011     alias testWithQualifiers = assertWithQualifiers!hasIndirections;
6012 
6013     {
6014         union U {}
6015         mixin testWithQualifiers!(U, false);
6016     }
6017     {
6018         static union U {}
6019         mixin testWithQualifiers!(U, false);
6020     }
6021 
6022     // Unions with members which aren't aggregate types and don't have indirections.
6023     foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
6024                           float, double, real, char, wchar, dchar, int function(string)))
6025     {
6026         // No indirections.
6027         {
6028             union U { T member; }
6029             mixin testWithQualifiers!(U, false);
6030         }
6031         {
6032             union U { const T member; }
6033             mixin testWithQualifiers!(U, false);
6034         }
6035         {
6036             union U { immutable T member; }
6037             mixin testWithQualifiers!(U, false);
6038         }
6039         {
6040             union U { shared T member; }
6041             mixin testWithQualifiers!(U, false);
6042         }
6043 
6044         // Pointers.
6045         {
6046             union U { T* member; }
6047             mixin testWithQualifiers!(U, true);
6048         }
6049         {
6050             union U { const(T)* member; }
6051             mixin testWithQualifiers!(U, true);
6052         }
6053         {
6054             union U { const T* member; }
6055             mixin testWithQualifiers!(U, true);
6056         }
6057         {
6058             union U { immutable T* member; }
6059             mixin testWithQualifiers!(U, true);
6060         }
6061         {
6062             union U { shared T* member; }
6063             mixin testWithQualifiers!(U, true);
6064         }
6065 
6066         // Dynamic arrays.
6067         {
6068             union U { T[] member; }
6069             mixin testWithQualifiers!(U, true);
6070         }
6071         {
6072             union U { const(T)[] member; }
6073             mixin testWithQualifiers!(U, true);
6074         }
6075         {
6076             union U { const T[] member; }
6077             mixin testWithQualifiers!(U, true);
6078         }
6079         {
6080             union U { immutable T[] member; }
6081             mixin testWithQualifiers!(U, true);
6082         }
6083         {
6084             union U { shared T[] member; }
6085             mixin testWithQualifiers!(U, true);
6086         }
6087 
6088         // Static arrays.
6089         {
6090             union U { T[1] member; }
6091             mixin testWithQualifiers!(U, false);
6092         }
6093         {
6094             union U { const(T)[1] member; }
6095             mixin testWithQualifiers!(U, false);
6096         }
6097         {
6098             union U { const T[1] member; }
6099             mixin testWithQualifiers!(U, false);
6100         }
6101         {
6102             union U { immutable T[1] member; }
6103             mixin testWithQualifiers!(U, false);
6104         }
6105         {
6106             union U { shared T[1] member; }
6107             mixin testWithQualifiers!(U, false);
6108         }
6109 
6110         // Static arrays of pointers.
6111         {
6112             union U { T*[1] member; }
6113             mixin testWithQualifiers!(U, true);
6114         }
6115         {
6116             union U { const(T)*[1] member; }
6117             mixin testWithQualifiers!(U, true);
6118         }
6119         {
6120             union U { const(T*)[1] member; }
6121             mixin testWithQualifiers!(U, true);
6122         }
6123         {
6124             union U { const T*[1] member; }
6125             mixin testWithQualifiers!(U, true);
6126         }
6127         {
6128             union U { immutable T*[1] member; }
6129             mixin testWithQualifiers!(U, true);
6130         }
6131         {
6132             union U { shared T*[1] member; }
6133             mixin testWithQualifiers!(U, true);
6134         }
6135 
6136         {
6137             union U { T*[0] member; }
6138             mixin testWithQualifiers!(U, false);
6139         }
6140         {
6141             union U { const(T)*[0] member; }
6142             mixin testWithQualifiers!(U, false);
6143         }
6144         {
6145             union U { const(T*)[0] member; }
6146             mixin testWithQualifiers!(U, false);
6147         }
6148         {
6149             union U { const T*[0] member; }
6150             mixin testWithQualifiers!(U, false);
6151         }
6152         {
6153             union U { immutable T*[0] member; }
6154             mixin testWithQualifiers!(U, false);
6155         }
6156         {
6157             union U { shared T*[0] member; }
6158             mixin testWithQualifiers!(U, false);
6159         }
6160 
6161         // Static arrays of dynamic arrays.
6162         {
6163             union U { T[][1] member; }
6164             mixin testWithQualifiers!(U, true);
6165         }
6166         {
6167             union U { const(T)[][1] member; }
6168             mixin testWithQualifiers!(U, true);
6169         }
6170         {
6171             union U { const(T[])[1] member; }
6172             mixin testWithQualifiers!(U, true);
6173         }
6174         {
6175             union U { const T[][1] member; }
6176             mixin testWithQualifiers!(U, true);
6177         }
6178         {
6179             union U { immutable T[][1] member; }
6180             mixin testWithQualifiers!(U, true);
6181         }
6182         {
6183             union U { shared T[][1] member; }
6184             mixin testWithQualifiers!(U, true);
6185         }
6186 
6187         {
6188             union U { T[][0] member; }
6189             mixin testWithQualifiers!(U, false);
6190         }
6191         {
6192             union U { const(T)[][0] member; }
6193             mixin testWithQualifiers!(U, false);
6194         }
6195         {
6196             union U { const(T[])[0] member; }
6197             mixin testWithQualifiers!(U, false);
6198         }
6199         {
6200             union U { const T[][0] member; }
6201             mixin testWithQualifiers!(U, false);
6202         }
6203         {
6204             union U { immutable T[][0] member; }
6205             mixin testWithQualifiers!(U, false);
6206         }
6207         {
6208             union U { shared T[][0] member; }
6209             mixin testWithQualifiers!(U, false);
6210         }
6211     }
6212 
6213     // Unions with arrays of void.
6214     {
6215         {
6216             static union U { void[] member; }
6217             mixin testWithQualifiers!(U, true);
6218         }
6219         {
6220             static union U { void[1] member; }
6221             mixin testWithQualifiers!(U, true);
6222         }
6223         {
6224             static union U { void[0] member; }
6225             mixin testWithQualifiers!(U, false);
6226         }
6227     }
6228 
6229     // Unions with multiple members, testing pointer types.
6230     {
6231         static union U { int i; bool b; }
6232         mixin testWithQualifiers!(U, false);
6233     }
6234     {
6235         static union U { int* i; bool b; }
6236         mixin testWithQualifiers!(U, true);
6237     }
6238     {
6239         static union U { int i; bool* b; }
6240         mixin testWithQualifiers!(U, true);
6241     }
6242     {
6243         static union U { int* i; bool* b; }
6244         mixin testWithQualifiers!(U, true);
6245     }
6246 
6247     // Unions with multiple members, testing dynamic arrays.
6248     {
6249         static union U { int[] arr; }
6250         mixin testWithQualifiers!(U, true);
6251     }
6252     {
6253         static union U { int i; int[] arr; }
6254         mixin testWithQualifiers!(U, true);
6255     }
6256     {
6257         static union U { int[] arr; int i; }
6258         mixin testWithQualifiers!(U, true);
6259     }
6260 
6261     // Unions with multiple members, testing static arrays.
6262     {
6263         static union U { int[1] arr; }
6264         mixin testWithQualifiers!(U, false);
6265     }
6266     {
6267         static union U { int i; int[1] arr; }
6268         mixin testWithQualifiers!(U, false);
6269     }
6270     {
6271         static union U { int[1] arr; int i; }
6272         mixin testWithQualifiers!(U, false);
6273     }
6274 
6275     {
6276         static union U { int*[0] arr; }
6277         mixin testWithQualifiers!(U, false);
6278     }
6279     {
6280         static union U { int i; int*[0] arr; }
6281         mixin testWithQualifiers!(U, false);
6282     }
6283     {
6284         static union U { int*[0] arr; int i; }
6285         mixin testWithQualifiers!(U, false);
6286     }
6287 
6288     {
6289         static union U { string[42] arr; }
6290         mixin testWithQualifiers!(U, true);
6291     }
6292     {
6293         static union U { int i; string[42] arr; }
6294         mixin testWithQualifiers!(U, true);
6295     }
6296     {
6297         static union U { string[42] arr; int i; }
6298         mixin testWithQualifiers!(U, true);
6299     }
6300 
6301     // Unions with associative arrays.
6302     {
6303         static union U { int[string] aa; }
6304         mixin testWithQualifiers!(U, true);
6305     }
6306     {
6307         static union U { int i; int[string] aa; }
6308         mixin testWithQualifiers!(U, true);
6309     }
6310     {
6311         static union U { int[string] aa; int i; }
6312         mixin testWithQualifiers!(U, true);
6313     }
6314 
6315     {
6316         static union U { int[42][int] aa; }
6317         mixin testWithQualifiers!(U, true);
6318     }
6319     {
6320         static union U { int[0][int] aa; }
6321         mixin testWithQualifiers!(U, true);
6322     }
6323 
6324     // Unions with classes.
6325     {
6326         class C {}
6327         union U { C c; }
6328         mixin testWithQualifiers!(U, true);
6329     }
6330     {
6331         interface I {}
6332         union U { I i; }
6333         mixin testWithQualifiers!(U, true);
6334     }
6335 
6336     // Unions with delegates.
6337     {
6338         union U { void delegate() d; }
6339         mixin testWithQualifiers!(U, true);
6340     }
6341     {
6342         union U { int delegate(int) d; }
6343         mixin testWithQualifiers!(U, true);
6344     }
6345 
6346     // Unions multiple layers deep.
6347     {
6348         union U1 { int i; }
6349         union U2 { U1 s; }
6350         union U3 { U2 s; }
6351         union U4 { U3 s; }
6352         union U5 { U4 s; }
6353         union U6 { U5 s; }
6354         union U7 { U6[0] s; }
6355         union U8 { U7 s; }
6356         union U9 { U8 s; }
6357         union U10 { U9 s; }
6358         mixin testWithQualifiers!(U1, false);
6359         mixin testWithQualifiers!(U2, false);
6360         mixin testWithQualifiers!(U3, false);
6361         mixin testWithQualifiers!(U4, false);
6362         mixin testWithQualifiers!(U5, false);
6363         mixin testWithQualifiers!(U6, false);
6364         mixin testWithQualifiers!(U7, false);
6365         mixin testWithQualifiers!(U8, false);
6366         mixin testWithQualifiers!(U9, false);
6367         mixin testWithQualifiers!(U10, false);
6368     }
6369     {
6370         union U1 { int* i; }
6371         union U2 { U1 s; }
6372         union U3 { U2 s; }
6373         union U4 { U3 s; }
6374         union U5 { U4 s; }
6375         union U6 { U5 s; }
6376         union U7 { U6[0] s; }
6377         union U8 { U7 s; }
6378         union U9 { U8 s; }
6379         union U10 { U9 s; }
6380         mixin testWithQualifiers!(U1, true);
6381         mixin testWithQualifiers!(U2, true);
6382         mixin testWithQualifiers!(U3, true);
6383         mixin testWithQualifiers!(U4, true);
6384         mixin testWithQualifiers!(U5, true);
6385         mixin testWithQualifiers!(U6, true);
6386         mixin testWithQualifiers!(U7, false);
6387         mixin testWithQualifiers!(U8, false);
6388         mixin testWithQualifiers!(U9, false);
6389         mixin testWithQualifiers!(U10, false);
6390     }
6391 }
6392 
6393 // hasIndirections with classes and interfaces
6394 @safe unittest
6395 {
6396     import phobos.sys.meta : AliasSeq;
6397 
6398     alias testWithQualifiers = assertWithQualifiers!hasIndirections;
6399 
6400     {
6401         class C {}
6402         mixin testWithQualifiers!(C, true);
6403     }
6404 
6405     foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
6406                           float, double, real, char, wchar, dchar, int function(string),
6407                           int[int], string delegate(int)))
6408     {
6409         {
6410             class C { T member; }
6411             mixin testWithQualifiers!(C, true);
6412         }
6413         {
6414             class C { const T member; }
6415             mixin testWithQualifiers!(C, true);
6416         }
6417         {
6418             class C { immutable T member; }
6419             mixin testWithQualifiers!(C, true);
6420         }
6421         {
6422             class C { shared T member; }
6423             mixin testWithQualifiers!(C, true);
6424         }
6425     }
6426 
6427     {
6428         interface I {}
6429         mixin testWithQualifiers!(I, true);
6430     }
6431 }
6432 
6433 /++
6434     Takes a type which is an associative array and evaluates to the type of the
6435     keys in that associative array.
6436 
6437     See_Also:
6438         $(LREF ValueType)
6439   +/
6440 alias KeyType(V : V[K], K) = K;
6441 
6442 ///
6443 @safe unittest
6444 {
6445     static assert(is(KeyType!(int[string]) == string));
6446     static assert(is(KeyType!(string[int]) == int));
6447 
6448     static assert(is(KeyType!(string[const int]) == const int));
6449     static assert(is(KeyType!(const int[string]) == string));
6450 
6451     struct S
6452     {
6453         int i;
6454     }
6455 
6456     string[S] aa1;
6457     static assert(is(KeyType!(typeof(aa1)) == S));
6458 
6459     S[string] aa2;
6460     static assert(is(KeyType!(typeof(aa2)) == string));
6461 
6462     KeyType!(typeof(aa1)) key1 = S(42);
6463     KeyType!(typeof(aa2)) key2 = "foo";
6464 
6465     // Key types with indirections have their inner layers treated as const
6466     // by the compiler, because the values of keys can't change, or the hash
6467     // value could change, putting the associative array in an invalid state.
6468     static assert(is(KeyType!(bool[string[]]) == const(string)[]));
6469     static assert(is(KeyType!(bool[int*]) == const(int)*));
6470 
6471     // If the given type is not an AA, then KeyType won't compile.
6472     static assert(!__traits(compiles, KeyType!int));
6473     static assert(!__traits(compiles, KeyType!(int[])));
6474 }
6475 
6476 /++
6477     Takes a type which is an associative array and evaluates to the type of the
6478     values in that associative array.
6479 
6480     See_Also:
6481         $(LREF KeyType)
6482   +/
6483 alias ValueType(V : V[K], K) = V;
6484 
6485 ///
6486 @safe unittest
6487 {
6488     static assert(is(ValueType!(int[string]) == int));
6489     static assert(is(ValueType!(string[int]) == string));
6490 
6491     static assert(is(ValueType!(string[const int]) == string));
6492     static assert(is(ValueType!(const int[string]) == const int));
6493 
6494     struct S
6495     {
6496         int i;
6497     }
6498 
6499     string[S] aa1;
6500     static assert(is(ValueType!(typeof(aa1)) == string));
6501 
6502     S[string] aa2;
6503     static assert(is(ValueType!(typeof(aa2)) == S));
6504 
6505     ValueType!(typeof(aa1)) value1 = "foo";
6506     ValueType!(typeof(aa2)) value2 = S(42);
6507 
6508     // If the given type is not an AA, then ValueType won't compile.
6509     static assert(!__traits(compiles, ValueType!int));
6510     static assert(!__traits(compiles, ValueType!(int[])));
6511 }
6512 
6513 /++
6514     Evaluates to the original / ultimate base type of an enum type - or for
6515     non-enum types, it evaluates to the type that it's given.
6516 
6517     If the base type of the given enum type is not an enum, then the result of
6518     OriginalType is its direct base type. However, if the base type of the
6519     given enum is also an enum, then OriginalType gives the ultimate base type
6520     - that is, it keeps getting the base type for each succesive enum in the
6521     chain until it gets to a base type that isn't an enum, and that's the
6522     result. So, the result will never be an enum type.
6523 
6524     If the given type has any qualifiers, the result will have those same
6525     qualifiers.
6526   +/
6527 version (StdDdoc) template OriginalType(T)
6528 {
6529     import core.internal.traits : CoreOriginalType = OriginalType;
6530     alias OriginalType = CoreOriginalType!T;
6531 }
6532 else
6533 {
6534     import core.internal.traits : CoreOriginalType = OriginalType;
6535     alias OriginalType = CoreOriginalType;
6536 }
6537 
6538 ///
6539 @safe unittest
6540 {
6541     enum E { a, b, c }
6542     static assert(is(OriginalType!E == int));
6543 
6544     enum F : E { x = E.a }
6545     static assert(is(OriginalType!F == int));
6546 
6547     enum G : F { y = F.x }
6548     static assert(is(OriginalType!G == int));
6549     static assert(is(OriginalType!(const G) == const int));
6550     static assert(is(OriginalType!(immutable G) == immutable int));
6551     static assert(is(OriginalType!(shared G) == shared int));
6552 
6553     enum C : char { a = 'a', b = 'b' }
6554     static assert(is(OriginalType!C == char));
6555 
6556     enum D : string { d = "dlang" }
6557     static assert(is(OriginalType!D == string));
6558 
6559     static assert(is(OriginalType!int == int));
6560     static assert(is(OriginalType!(const long) == const long));
6561     static assert(is(OriginalType!string == string));
6562 
6563     // OriginalType gets the base type of enums and for all other types gives
6564     // the same type back. It does nothing special for other types - like
6565     // classes - where one could talk about the type having a base type.
6566     class Base {}
6567     class Derived : Base {}
6568     static assert(is(OriginalType!Base == Base));
6569     static assert(is(OriginalType!Derived == Derived));
6570 }
6571 
6572 /++
6573     PropertyType evaluates to the type of the symbol as an expression (i.e. the
6574     type of the expression when the symbol is used in an expression by itself),
6575     and SymbolType evaluates to the type of the given symbol as a symbol (i.e.
6576     the type of the symbol itself).
6577 
6578     Unlike with $(K_TYPEOF), $(K_PROPERTY) has no effect on the result of
6579     either PropertyType or SymbolType.
6580 
6581     TLDR, PropertyType should be used when code is going to use a symbol as if
6582     it were a getter property (without caring whether the symbol is a variable
6583     or a function), and the code needs to know the type of that property and
6584     $(I not) the type of the symbol itself (since with functions, they're not
6585     the same thing). So, it's treating the symbol as an expression on its own
6586     and giving the type of that expression rather than giving the type of the
6587     symbol itself. And it's named PropertyType rather than something like
6588     $(D ExpressionType), because it's used in situations where the code is
6589     treating the symbol as a getter property, and it does not operate on
6590     expressions in general. SymbolType should then be used in situations where
6591     the code needs to know the type of the symbol itself.
6592 
6593     As for why PropertyType and SymbolType are necessary, and $(K_TYPEOF) is
6594     not sufficient, $(K_TYPEOF) gives both the types of symbols and the types
6595     of expressions. When it's given something that's clearly an expression -
6596     e.g. $(D typeof(foo + bar)) or $(D typeof(foo())), then the result is the
6597     type of that expression. However, when $(K_TYPEOF) is given a symbol, what
6598     $(K_TYPEOF) does depends on the symbol, which can make using it correctly
6599     in generic code difficult.
6600 
6601     For symbols that don't have types, naturally, $(K_TYPEOF) doesn't even
6602     compile (e.g. $(D typeof(int)) won't compile, because in D, types don't
6603     themselves have types), so the question is what happens with $(K_TYPEOF)
6604     and symbols which do have types.
6605 
6606     For symbols which have types and are not functions, what $(K_TYPEOF) does
6607     is straightforward, because there is no difference between the type of the
6608     symbol and the type of the expression - e.g. if $(D foo) is a variable of
6609     type $(K_INT), then $(D typeof(foo)) would be $(K_INT), because the
6610     variable itself is of type $(K_INT), and if the variable is used as an
6611     expression (e.g. when it's returned from a function or passed to a
6612     function), then that expression is also of type $(K_INT).
6613 
6614     However, for functions (particularly functions which don't require
6615     arguments), things aren't as straightforward. Should $(D typeof(foo)) give
6616     the type of the function itself or the type of the expression? If parens
6617     always had to be used when calling a function, then $(D typeof(foo)) would
6618     clearly be the type of the function itself, whereas $(D typeof(foo()))
6619     would be the type of the expression (which would be the return type of the
6620     function so long as $(D foo) could be called with no arguments, and it
6621     wouldn't compile otherwise, because the expression would be invalid).
6622     However, because parens are optional when calling a function that has no
6623     arguments, $(D typeof(foo)) is ambiguous. There's no way to know which the
6624     programmer actually intended, but the compiler has to either make it an
6625     error or choose between giving the type of the symbol or the type of the
6626     expression.
6627 
6628     So, the issue here is functions which can be treated as getter properties,
6629     because they can be called without parens and thus syntactically look
6630     exactly like a variable when they're used. Any function which requires
6631     arguments (including when a function is used as a setter property) does not
6632     have this problem, because it isn't a valid expression when used on its own
6633     (it needs to be assigned to or called with parens in order to be a valid
6634     expression).
6635 
6636     What the compiler currently does when it encounters this ambiguity depends
6637     on the $(K_PROPERTY) attribute. If the function does not have the
6638     $(K_PROPERTY) attribute, then $(D typeof(foo)) will give the type of the
6639     symbol - e.g. $(D int()) if the signature for $(D foo) were $(D int foo()).
6640     However, if the function $(I does) have the $(K_PROPERTY) attribute, then
6641     $(D typeof(foo)) will give the type of the expression. So, if $(D foo) were
6642     $(D @property int foo()), then $(D typeof(foo)) would give $(K_INT) rather
6643     than $(D int()). The idea behind this is that $(K_PROPERTY) functions are
6644     supposed to act like variables, and using $(K_TYPEOF) on a variable of type
6645     $(K_INT) would give $(K_INT), not $(D int()). So, with this behavior of
6646     $(K_TYPEOF), a $(K_PROPERTY) function is closer to being a drop-in
6647     replacement for a variable.
6648 
6649     The problem with this though is two-fold. One, it means that $(K_TYPEOF)
6650     cannot be relied on to give the type of the symbol when given a symbol on
6651     its own, forcing code that needs the actual type of the symbol to work
6652     around $(K_PROPERTY). And two, because parens are optional on functions
6653     which can be called without arguments, whether the function is marked with
6654     $(K_PROPERTY) or not is irrevelant to whether the symbol is going to be
6655     used as if it were a variable, and so it's irrelevant to code that's trying
6656     to get the type of the expression when the symbol is used like a getter
6657     property. If optional parens were removed from the language (as was
6658     originally the intent when $(K_PROPERTY) was introduced), then that would
6659     fix the second problem, but it would still leave the first problem.
6660 
6661     So, $(K_PROPERTY) is solving the problem in the wrong place. It's the code
6662     doing the type introspection which needs to decide whether to get the type
6663     of a symbol as if it were a getter property or whether to get the type of
6664     the symbol itself. It's the type introspection code which knows which is
6665     relevant for what it's doing, and a function could be used both in code
6666     which needs to treat it as a getter property and in code which needs to get
6667     the type of the symbol itself (e.g. because it needs to get the attributes
6668     on the function).
6669 
6670     All of this means that $(K_TYPEOF) by itself is unreliable when used on a
6671     symbol. In practice, the programmer needs to indicate whether they want the
6672     type of the symbol itself or the type of the symbol as a getter property in
6673     an expression, and leaving it up to $(K_TYPEOF) is simply too error-prone.
6674     So, ideally, $(K_TYPEOF) would be split up into two separate constructs,
6675     but that would involve adding more keywords (and break a lot of existing
6676     code if $(K_TYPEOF) were actually removed).
6677 
6678     So, phobos.sys.traits provides SymbolType and PropertyType. They're both
6679     traits that take a symbol and give the type for that symbol. However,
6680     SymbolType gives the type of the symbol itself, whereas PropertyType gives
6681     the type of the symbol as if it were used as a getter property in an
6682     expression. Neither is affected by whether the symbol is marked with
6683     $(K_PROPERTY). So, code that needs to get information about the symbol
6684     itself should use SymbolType rather than $(K_TYPEOF) or PropertyType,
6685     whereas code that needs to get the type of the symbol as a getter property
6686     within an expression should use PropertyType.
6687 
6688     The use of $(K_TYPEOF) should then be restricted to situations where code
6689     is getting the type of an expression which isn't a symbol (or code where
6690     it's already known that the symbol isn't a function). Also, since
6691     template alias parameters only accept symbols, any expressions which aren't
6692     symbols won't compile with SymbolType or PropertyType anyway.
6693 
6694     SymbolType and PropertyType must be given a symbol which has a type (so,
6695     not something like a type or an uninstantiated template). Symbols
6696     which don't have types will fail the template constraint.
6697 
6698     For both SymbolType and PropertyType, if they are given a symbol which has
6699     a type, and that symbol is not a function, the result will be the same as
6700     $(K_TYPEOF) (since in such cases, the type of the symbol and the type of
6701     the expression are the same). The difference comes in with functions.
6702 
6703     When SymbolType is given any symbol which is a function, the result will be
6704     the type of the function itself regardless of whether the function is
6705     marked with $(K_PROPERTY). This makes it so that in all situations where
6706     the type of the symbol is needed, SymbolType can be used to get the type of
6707     the symbol without having to worry about whether it's a function marked
6708     with $(K_PROPERTY).
6709 
6710     When PropertyType is given any function which can be used as a getter
6711     property, the result will be the type of the symbol as an expression - i.e.
6712     the return type of the function (in effect, this means that it treats all
6713     functions as if they were marked with $(K_PROPERTY)). Whether the function
6714     is actually marked with $(K_PROPERTY) or not is irrelevant.
6715 
6716     If PropertyType is given any function which which cannot be used as a
6717     getter property (i.e. it requires arguments or returns $(K_VOID)), the
6718     template constraint will reject it, and PropertyType will fail to compile.
6719     This is equivalent to what $(K_TYPEOF) does when it's given a $(K_PROPERTY)
6720     function which is a setter, since it's not a valid expression on its own.
6721 
6722     So, for $(D PropertyType!foo), if $(D foo) is a function, the result is
6723     equivalent to $(D typeof(foo())) (and for non-functions, it's equivalent to
6724     $(D typeof(foo))).
6725 
6726     To summarize, SymbolType should be used when code needs to get the type of
6727     the symbol itself; PropertyType should be used when code needs to get the
6728     type of the symbol when it's used in an expression as a getter property
6729     (generally because the code doesn't care whether the symbol is a variable
6730     or a function); and $(K_TYPEOF) should be used when getting the type of an
6731     expression which is not a symbol.
6732 
6733     See_Also:
6734         $(DDSUBLINK spec/type, typeof, The language spec for typeof)
6735   +/
6736 template PropertyType(alias sym)
6737 if (is(typeof(sym)) && (!is(typeof(sym) == return) ||
6738                         (is(typeof(sym())) && !is(typeof(sym()) == void))))
6739 {
6740     // This handles functions which don't have a context pointer.
6741     static if (is(typeof(&sym) == T*, T) && is(T == function))
6742     {
6743         // Note that we can't use is(T R == return) to get the return type,
6744         // because the first overload isn't necessarily the getter function,
6745         // and is(T R == return) will give us the first overload if the function
6746         // doesn't have @property on it (whereas if it does have @property, it
6747         // will give use the getter if there is one). However, we at least know
6748         // that there's a getter function, because the template constraint
6749         // validates that sym() compiles (and returns something) if it's a
6750         // function, function pointer, or delegate.
6751         alias PropertyType = typeof(sym());
6752     }
6753     // This handles functions which do have a context pointer.
6754     else static if (is(typeof(&sym) T == delegate) && is(T R == return))
6755     {
6756         // See the comment above for why we can't get the return type the
6757         // normal way.
6758         alias PropertyType = typeof(sym());
6759     }
6760     // This handles everything which isn't a function.
6761     else
6762         alias PropertyType = typeof(sym);
6763 }
6764 
6765 /++ Ditto +/
6766 template SymbolType(alias sym)
6767 if (!is(sym))
6768 {
6769     // This handles functions which don't have a context pointer.
6770     static if (is(typeof(&sym) == T*, T) && is(T == function))
6771         alias SymbolType = T;
6772     // This handles functions which do have a context pointer.
6773     else static if (is(typeof(&sym) T == delegate))
6774         alias SymbolType = T;
6775     // This handles everything which isn't a function.
6776     else
6777         alias SymbolType = typeof(sym);
6778 }
6779 
6780 ///
6781 @safe unittest
6782 {
6783     int i;
6784     static assert( is(SymbolType!i == int));
6785     static assert( is(PropertyType!i == int));
6786     static assert( is(typeof(i) == int));
6787 
6788     string str;
6789     static assert( is(SymbolType!str == string));
6790     static assert( is(PropertyType!str == string));
6791     static assert( is(typeof(str) == string));
6792 
6793     // ToFunctionType is used here to get around the fact that we don't have a
6794     // way to write out function types in is expressions (whereas we can write
6795     // out the type of a function pointer), which is a consequence of not being
6796     // able to declare variables with a function type (as opposed to a function
6797     // pointer type). That being said, is expressions are pretty much the only
6798     // place where writing out a function type would make sense.
6799 
6800     // The function type has more attributes than the function declaration,
6801     // because the attributes are inferred for nested functions.
6802 
6803     static string func() { return ""; }
6804     static assert( is(SymbolType!func ==
6805                       ToFunctionType!(string function()
6806                                       @safe pure nothrow @nogc)));
6807     static assert( is(PropertyType!func == string));
6808     static assert( is(typeof(func) == SymbolType!func));
6809 
6810     int function() funcPtr;
6811     static assert( is(SymbolType!funcPtr == int function()));
6812     static assert( is(PropertyType!funcPtr == int function()));
6813     static assert( is(typeof(funcPtr) == int function()));
6814 
6815     int delegate() del;
6816     static assert( is(SymbolType!del == int delegate()));
6817     static assert( is(PropertyType!del == int delegate()));
6818     static assert( is(typeof(del) == int delegate()));
6819 
6820     @property static int prop() { return 0; }
6821     static assert( is(SymbolType!prop ==
6822                       ToFunctionType!(int function()
6823                                       @property @safe pure nothrow @nogc)));
6824     static assert( is(PropertyType!prop == int));
6825     static assert( is(typeof(prop) == PropertyType!prop));
6826 
6827     // Functions which cannot be used as getter properties (i.e. they require
6828     // arguments and/or return void) do not compile with PropertyType.
6829     static int funcWithArg(int i) { return i; }
6830     static assert( is(SymbolType!funcWithArg ==
6831                       ToFunctionType!(int function(int)
6832                                       @safe pure nothrow @nogc)));
6833     static assert(!__traits(compiles, PropertyType!funcWithArg));
6834     static assert( is(typeof(funcWithArg) == SymbolType!funcWithArg));
6835 
6836     // Setter @property functions also don't work with typeof, because typeof
6837     // gets the type of the expression rather than the type of the symbol when
6838     // the symbol is a function with @property, and a setter property is not a
6839     // valid expression on its own.
6840     @property static void prop2(int) {}
6841     static assert( is(SymbolType!prop2 ==
6842                       ToFunctionType!(void function(int)
6843                                       @property @safe pure nothrow @nogc)));
6844     static assert(!__traits(compiles, PropertyType!prop2));
6845     static assert(!__traits(compiles, typeof(prop2)));
6846 
6847     // Expressions which aren't symbols don't work with alias parameters and
6848     // thus don't work with SymbolType or PropertyType.
6849     static assert(!__traits(compiles, PropertyType!(i + 42)));
6850     static assert(!__traits(compiles, SymbolType!(i + 42)));
6851     static assert( is(typeof(i + 42) == int));
6852 
6853     // typeof will work with a function that takes arguments so long as it's
6854     // used in a proper expression.
6855     static assert( is(typeof(funcWithArg(42)) == int));
6856     static assert( is(typeof(prop2 = 42) == void));
6857     static assert( is(typeof(prop2(42)) == void));
6858 }
6859 
6860 /++
6861     With templated types or functions, a specific instantiation should be
6862     passed to SymbolType or PropertyType, not the symbol for the template
6863     itself. If $(K_TYPEOF), SymbolType, or PropertyType is used on a template
6864     (rather than an instantiation of the template), the result will be
6865     $(K_VOID), because the template itself does not have a type.
6866   +/
6867 @safe unittest
6868 {
6869     static T func(T)() { return T.init; }
6870 
6871     static assert(is(SymbolType!func == void));
6872     static assert(is(PropertyType!func == void));
6873     static assert(is(typeof(func) == void));
6874 
6875     static assert(is(SymbolType!(func!int) ==
6876                      ToFunctionType!(int function()
6877                                      @safe pure nothrow @nogc)));
6878     static assert(is(PropertyType!(func!int) == int));
6879     static assert(is(typeof(func!int) == SymbolType!(func!int)));
6880 
6881     static assert(is(SymbolType!(func!string) ==
6882                      ToFunctionType!(string function()
6883                                      @safe pure nothrow @nogc)));
6884     static assert(is(PropertyType!(func!string) == string));
6885     static assert(is(typeof(func!string) == SymbolType!(func!string)));
6886 }
6887 
6888 /++
6889     If a function is overloaded, then when using it as a symbol to pass to
6890     $(K_TYPEOF), the compiler typically selects the first overload. However, if
6891     the functions are marked with $(K_PROPERTY), and one of the overloads is a
6892     getter property, then $(K_TYPEOF) will select the getter property (or fail
6893     to compile if they're all setter properties). This is because it's getting
6894     the type of the function as an expression rather than doing introspection
6895     on the function itself.
6896 
6897     SymbolType always gives the type of the first overload (effectively ignoring
6898     $(K_PROPERTY)), and PropertyType always gives the getter ovrerload
6899     (effectively treating all functions as if they had $(K_PROPERTY)).
6900 
6901     If code needs to get the symbol for a specific overload, then
6902     $(DDSUBLINK spec/traits, getOverloads, $(D __traits(getOverloads, ...))
6903     must be used.
6904 
6905     In general, $(D getOverloads) should be used when using SymbolType, since
6906     there's no guarantee that the first one is the correct one (and often, code
6907     will need to check all of the overloads), whereas with PropertyType, it
6908     doesn't usually make sense to get specific overloads, because there can
6909     only ever be one overload which works as a getter property, and using
6910     PropertyType on the symbol for the function will give that overload if it's
6911     present, regardless of which overload is first (and it will fail to compile
6912     if there is no overload which can be called as a getter).
6913   +/
6914 @safe unittest
6915 {
6916     static struct S
6917     {
6918         string foo();
6919         void foo(string);
6920         bool foo(string, int);
6921 
6922         @property void bar(int);
6923         @property int bar();
6924     }
6925 
6926     {
6927         static assert( is(SymbolType!(S.foo) ==
6928                           ToFunctionType!(string function())));
6929         static assert( is(PropertyType!(S.foo) == string));
6930         static assert( is(typeof(S.foo) == SymbolType!(S.foo)));
6931 
6932         alias overloads = __traits(getOverloads, S, "foo");
6933 
6934         // string foo();
6935         static assert( is(SymbolType!(overloads[0]) == function));
6936         static assert( is(PropertyType!(overloads[0]) == string));
6937         static assert( is(typeof(overloads[0]) == function));
6938 
6939         static assert( is(SymbolType!(overloads[0]) ==
6940                           ToFunctionType!(string function())));
6941         static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
6942 
6943         // void foo(string);
6944         static assert( is(SymbolType!(overloads[1]) == function));
6945         static assert(!__traits(compiles, PropertyType!(overloads[1])));
6946         static assert( is(typeof(overloads[1]) == function));
6947 
6948         static assert( is(SymbolType!(overloads[1]) ==
6949                           ToFunctionType!(void function(string))));
6950         static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
6951 
6952         // void foo(string, int);
6953         static assert( is(SymbolType!(overloads[2]) == function));
6954         static assert(!__traits(compiles, PropertyType!(overloads[2])));
6955         static assert( is(typeof(overloads[2]) == function));
6956 
6957         static assert( is(SymbolType!(overloads[2]) ==
6958                           ToFunctionType!(bool function(string, int))));
6959         static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2])));
6960     }
6961     {
6962         static assert( is(SymbolType!(S.bar) ==
6963                           ToFunctionType!(void function(int) @property)));
6964         static assert( is(PropertyType!(S.bar) == int));
6965         static assert( is(typeof(S.bar) == PropertyType!(S.bar)));
6966 
6967         alias overloads = __traits(getOverloads, S, "bar");
6968 
6969         // @property void bar(int);
6970         static assert( is(SymbolType!(overloads[0]) == function));
6971         static assert(!__traits(compiles, PropertyType!(overloads[0])));
6972         static assert(!__traits(compiles, typeof(overloads[0])));
6973 
6974         static assert( is(SymbolType!(overloads[0]) ==
6975                           ToFunctionType!(void function(int) @property)));
6976 
6977         // @property int bar();
6978         static assert( is(SymbolType!(overloads[1]) == function));
6979         static assert( is(PropertyType!(overloads[1]) == int));
6980         static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
6981 
6982         static assert( is(SymbolType!(overloads[1]) ==
6983                           ToFunctionType!(int function() @property)));
6984     }
6985 }
6986 
6987 @safe unittest
6988 {
6989     {
6990         string str;
6991         int i;
6992 
6993         static assert(!__traits(compiles, SymbolType!int));
6994         static assert(!__traits(compiles, SymbolType!(str ~ "more str")));
6995         static assert(!__traits(compiles, SymbolType!(i + 42)));
6996         static assert(!__traits(compiles, SymbolType!(&i)));
6997 
6998         static assert(!__traits(compiles, PropertyType!int));
6999         static assert(!__traits(compiles, PropertyType!(str ~ "more str")));
7000         static assert(!__traits(compiles, PropertyType!(i + 42)));
7001         static assert(!__traits(compiles, PropertyType!(&i)));
7002     }
7003 
7004     static assert( is(SymbolType!42 == int));
7005     static assert( is(SymbolType!"dlang" == string));
7006 
7007     int var;
7008 
7009     int funcWithContext() { return var; }
7010     static assert( is(SymbolType!funcWithContext ==
7011                       ToFunctionType!(int function()
7012                                       @safe pure nothrow @nogc)));
7013     static assert( is(PropertyType!funcWithContext == int));
7014     static assert( is(typeof(funcWithContext) == SymbolType!funcWithContext));
7015 
7016     @property int propWithContext() { return var; }
7017     static assert( is(SymbolType!propWithContext == function));
7018     static assert( is(SymbolType!propWithContext ==
7019                       ToFunctionType!(int function() @property @safe pure nothrow @nogc)));
7020     static assert( is(PropertyType!propWithContext == int));
7021     static assert( is(typeof(propWithContext) == PropertyType!propWithContext));
7022 
7023     // For those who might be confused by this sort of declaration, this is a
7024     // property function which returns a function pointer that takes no
7025     // arguments and returns int, which gets an even uglier signature when
7026     // writing out the type for a pointer to such a property function.
7027     static int function() propFuncPtr() @property { return null; }
7028     static assert( is(SymbolType!propFuncPtr == function));
7029     static assert( is(SymbolType!propFuncPtr ==
7030                       ToFunctionType!(int function() function() @property @safe pure nothrow @nogc)));
7031     static assert( is(PropertyType!propFuncPtr == int function()));
7032     static assert( is(typeof(propFuncPtr) == PropertyType!propFuncPtr));
7033 
7034     static int delegate() propDel() @property { return null; }
7035     static assert( is(SymbolType!propDel == function));
7036     static assert( is(SymbolType!propDel ==
7037                       ToFunctionType!(int delegate() function() @property @safe pure nothrow @nogc)));
7038     static assert( is(PropertyType!propDel == int delegate()));
7039     static assert( is(typeof(propDel) == PropertyType!propDel));
7040 
7041     int function() propFuncPtrWithContext() @property { ++var; return null; }
7042     static assert( is(SymbolType!propFuncPtrWithContext == function));
7043     static assert( is(SymbolType!propFuncPtrWithContext ==
7044                       ToFunctionType!(int function() function() @property @safe pure nothrow @nogc)));
7045     static assert( is(PropertyType!propFuncPtrWithContext == int function()));
7046     static assert( is(typeof(propFuncPtrWithContext) == PropertyType!propFuncPtrWithContext));
7047 
7048     int delegate() propDelWithContext() @property { ++var; return null; }
7049     static assert( is(SymbolType!propDelWithContext == function));
7050     static assert( is(SymbolType!propDelWithContext ==
7051                       ToFunctionType!(int delegate() function() @property @safe pure nothrow @nogc)));
7052     static assert( is(PropertyType!propDelWithContext == int delegate()));
7053     static assert( is(typeof(propDelWithContext) == PropertyType!propDelWithContext));
7054 
7055     const int ci;
7056     static assert( is(SymbolType!ci == const int));
7057     static assert( is(PropertyType!ci == const int));
7058     static assert( is(typeof(ci) == PropertyType!ci));
7059 
7060     shared int si;
7061     static assert( is(SymbolType!si == shared int));
7062     static assert( is(PropertyType!si == shared int));
7063     static assert( is(typeof(si) == PropertyType!si));
7064 
7065     static struct S
7066     {
7067         int i;
7068         @disable this(this);
7069     }
7070     static assert(!__traits(isCopyable, S));
7071 
7072     S s;
7073     static assert( is(SymbolType!s == S));
7074     static assert( is(PropertyType!s == S));
7075     static assert( is(typeof(s) == SymbolType!s));
7076 
7077     static ref S foo();
7078     static void bar(ref S);
7079 
7080     static @property ref S bob();
7081     static @property void sally(ref S);
7082 
7083     // The aliases are due to https://github.com/dlang/dmd/issues/17505
7084     // Apparently, aliases are special-cased to work with function pointer
7085     // signatures which return by ref, and we can't do it elsewhere.
7086     alias FooPtr = ref S function();
7087     static assert( is(SymbolType!foo == ToFunctionType!FooPtr));
7088     static assert( is(PropertyType!foo == S));
7089     static assert( is(typeof(foo) == SymbolType!foo));
7090 
7091     static assert( is(SymbolType!bar == ToFunctionType!(void function(ref S))));
7092     static assert(!__traits(compiles, PropertyType!bar));
7093     static assert( is(typeof(bar) == SymbolType!bar));
7094 
7095     alias BobPtr = ref S function() @property;
7096     static assert( is(SymbolType!bob == ToFunctionType!BobPtr));
7097     static assert( is(PropertyType!bob == S));
7098     static assert( is(typeof(bob) == S));
7099     static assert( is(typeof(bob) == PropertyType!bob));
7100 
7101     static assert( is(SymbolType!sally == ToFunctionType!(void function(ref S) @property)));
7102     static assert(!__traits(compiles, PropertyType!sally));
7103     static assert(!__traits(compiles, typeof(sally)));
7104 
7105     string defaultArgs1(int i = 0);
7106     void defaultArgs2(string, int i = 0);
7107 
7108     static assert( is(SymbolType!defaultArgs1 == ToFunctionType!(string function(int))));
7109     static assert( is(PropertyType!defaultArgs1 == string));
7110     static assert( is(typeof(defaultArgs1) == SymbolType!defaultArgs1));
7111 
7112     static assert( is(SymbolType!defaultArgs2 == ToFunctionType!(void function(string, int))));
7113     static assert(!__traits(compiles, PropertyType!defaultArgs2));
7114     static assert( is(typeof(defaultArgs2) == SymbolType!defaultArgs2));
7115 
7116     @property string defaultArgsProp1(int i = 0);
7117     @property void defaultArgsProp2(string, int i = 0);
7118 
7119     static assert( is(SymbolType!defaultArgsProp1 == ToFunctionType!(string function(int) @property)));
7120     static assert( is(PropertyType!defaultArgsProp1 == string));
7121     static assert( is(typeof(defaultArgsProp1) == PropertyType!defaultArgsProp1));
7122 
7123     static assert( is(SymbolType!defaultArgsProp2 == ToFunctionType!(void function(string, int) @property)));
7124     static assert(!__traits(compiles, PropertyType!defaultArgsProp2));
7125     static assert(!__traits(compiles, typeof(defaultArgsProp2)));
7126 
7127     int returningSetter(string);
7128     @property int returningSetterProp(string);
7129 
7130     static assert( is(SymbolType!returningSetter == ToFunctionType!(int function(string))));
7131     static assert(!__traits(compiles, PropertyType!returningSetter));
7132     static assert( is(typeof(returningSetter) == SymbolType!returningSetter));
7133 
7134     static assert( is(SymbolType!returningSetterProp == ToFunctionType!(int function(string) @property)));
7135     static assert(!__traits(compiles, PropertyType!returningSetterProp));
7136     static assert(!__traits(compiles, typeof(returningSetterProp)));
7137 }
7138 
7139 // These are for the next unittest block to test overloaded free functions (in
7140 // addition to the overloaded member functions and static functions that it
7141 // tests). That way, if there are any differences in how free functions and
7142 // member functions are handled, we'll catch those bugs (be they compiler bugs
7143 // or bugs in phobos.sys.traits).
7144 version (PhobosUnittest)
7145 {
7146     private void modFunc1();
7147     private void modFunc1(string);
7148     private int modFunc1(string, int);
7149 
7150     private int modFunc2();
7151     private int modFunc2(string);
7152     private string modFunc2(string, int);
7153 
7154     private void modFunc3(int*);
7155     private void modFunc3(float);
7156     private string modFunc3(int a = 0);
7157 
7158     private int modGetterFirst();
7159     private void modGetterFirst(int);
7160 
7161     private void modSetterFirst(int);
7162     private int modSetterFirst();
7163 
7164     private void modSetterOnly(string);
7165     private void modSetterOnly(int);
7166 
7167     private @property int modPropGetterFirst();
7168     private @property void modPropGetterFirst(int);
7169 
7170     private @property void modPropSetterFirst(int);
7171     private @property int modPropSetterFirst();
7172 
7173     private @property void modPropSetterOnly(string);
7174     private @property void modPropSetterOnly(int);
7175 
7176     private int function() @property modGetterFirstFuncPtr();
7177     private void modGetterFirstFuncPtr(int function() @property);
7178 
7179     private void modSetterFirstFuncPtr(int function() @property);
7180     private int function() @property modSetterFirstFuncPtr();
7181 
7182     private int function() @property modPropGetterFirstFuncPtr() @property;
7183     private void modPropGetterFirstFuncPtr(int function() @property) @property;
7184 
7185     private void modPropSetterFirstFuncPtr(int function() @property) @property;
7186     private int function() @property modPropSetterFirstFuncPtr() @property;
7187 }
7188 
7189 @safe unittest
7190 {
7191     // Note that with overloads without @property, typeof gives the first
7192     // overload, whereas with overloads with @property, typeof gives the return
7193     // type of the getter overload no matter where it is in the order.
7194     // PropertyType needs to always give the getter overload whether @property
7195     // is used or not, since that's the type of the symbol when used as a
7196     // getter property in an expression.
7197     {
7198         alias module_ = __traits(parent, __traits(parent, {}));
7199 
7200         // void modFunc1();
7201         // void modFunc1(string);
7202         // int modFunc1(string, int);
7203         {
7204             static assert( is(SymbolType!modFunc1 == ToFunctionType!(void function())));
7205             static assert(!__traits(compiles, PropertyType!modFunc1));
7206             static assert( is(typeof(modFunc1) == SymbolType!modFunc1));
7207 
7208             alias overloads = __traits(getOverloads, module_, "modFunc1");
7209             static assert(overloads.length == 3);
7210 
7211             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function())));
7212             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7213             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7214 
7215             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string))));
7216             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7217             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7218 
7219             static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(int function(string, int))));
7220             static assert(!__traits(compiles, PropertyType!(overloads[2])));
7221             static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2])));
7222         }
7223 
7224         // int modFunc2();
7225         // int modFunc2(string);
7226         // string modFunc2(string, int);
7227         {
7228             static assert( is(SymbolType!modFunc2 == ToFunctionType!(int function())));
7229             static assert( is(PropertyType!modFunc2 == int));
7230             static assert( is(typeof(modFunc2) == SymbolType!modFunc2));
7231 
7232             alias overloads = __traits(getOverloads, module_, "modFunc2");
7233             static assert(overloads.length == 3);
7234 
7235             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function())));
7236             static assert( is(PropertyType!(overloads[0]) == int));
7237             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7238 
7239             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string))));
7240             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7241             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7242 
7243             static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(string function(string, int))));
7244             static assert(!__traits(compiles, PropertyType!(overloads[2])));
7245             static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2])));
7246         }
7247 
7248         // void modFunc3(int*);
7249         // void modFunc3(float);
7250         // string modFunc3(int a = 0);
7251         {
7252             static assert( is(SymbolType!modFunc3 == ToFunctionType!(void function(int*))));
7253             static assert( is(PropertyType!modFunc3 == string));
7254             static assert( is(typeof(modFunc3) == SymbolType!modFunc3));
7255 
7256             alias overloads = __traits(getOverloads, module_, "modFunc3");
7257             static assert(overloads.length == 3);
7258 
7259             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int*))));
7260             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7261             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7262 
7263             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(float))));
7264             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7265             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7266 
7267             static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(string function(int))));
7268             static assert( is(PropertyType!(overloads[2]) == string));
7269             static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2])));
7270         }
7271 
7272         // int modGetterFirst();
7273         // void modGetterFirst(int);
7274         {
7275             static assert( is(SymbolType!modGetterFirst == ToFunctionType!(int function())));
7276             static assert( is(PropertyType!modGetterFirst == int));
7277             static assert( is(typeof(modGetterFirst) == SymbolType!modGetterFirst));
7278 
7279             alias overloads = __traits(getOverloads, module_, "modGetterFirst");
7280             static assert(overloads.length == 2);
7281 
7282             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function())));
7283             static assert( is(PropertyType!(overloads[0]) == int));
7284             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7285 
7286             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int))));
7287             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7288             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7289         }
7290 
7291         // void modSetterFirst(int);
7292         // int modSetterFirst();
7293         {
7294             static assert( is(SymbolType!modSetterFirst == ToFunctionType!(void function(int))));
7295             static assert( is(PropertyType!modSetterFirst == int));
7296             static assert( is(typeof(modSetterFirst) == SymbolType!modSetterFirst));
7297 
7298             alias overloads = __traits(getOverloads, module_, "modSetterFirst");
7299             static assert(overloads.length == 2);
7300 
7301             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int))));
7302             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7303             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7304 
7305             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function())));
7306             static assert( is(PropertyType!(overloads[1]) == int));
7307             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7308         }
7309 
7310         // void modSetterOnly(string);
7311         // void modSetterOnly(int);
7312         {
7313             static assert( is(SymbolType!modSetterOnly == ToFunctionType!(void function(string))));
7314             static assert(!__traits(compiles, PropertyType!modSetterOnly));
7315             static assert( is(typeof(modSetterOnly) == SymbolType!modSetterOnly));
7316 
7317             alias overloads = __traits(getOverloads, module_, "modSetterOnly");
7318             static assert(overloads.length == 2);
7319 
7320             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string))));
7321             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7322             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7323 
7324             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int))));
7325             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7326             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7327         }
7328 
7329         // @property int modPropGetterFirst();
7330         // @property void modPropGetterFirst(int);
7331         {
7332             static assert( is(SymbolType!modPropGetterFirst == ToFunctionType!(int function() @property)));
7333             static assert( is(PropertyType!modPropGetterFirst == int));
7334             static assert( is(typeof(modPropGetterFirst) == PropertyType!modPropGetterFirst));
7335 
7336             alias overloads = __traits(getOverloads, module_, "modPropGetterFirst");
7337             static assert(overloads.length == 2);
7338 
7339             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function() @property)));
7340             static assert( is(PropertyType!(overloads[0]) == int));
7341             static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
7342 
7343             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int) @property)));
7344             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7345             static assert(!__traits(compiles, typeof((overloads[1]))));
7346         }
7347 
7348         // @property void modPropSetterFirst(int);
7349         // @property int modPropSetterFirst();
7350         {
7351             static assert( is(SymbolType!modPropSetterFirst == ToFunctionType!(void function(int) @property)));
7352             static assert( is(PropertyType!modPropSetterFirst == int));
7353             static assert( is(typeof(modPropSetterFirst) == PropertyType!modPropSetterFirst));
7354 
7355             alias overloads = __traits(getOverloads, module_, "modPropSetterFirst");
7356             static assert(overloads.length == 2);
7357 
7358             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property)));
7359             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7360             static assert(!__traits(compiles, typeof(overloads[0])));
7361 
7362             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property)));
7363             static assert( is(PropertyType!(overloads[1]) == int));
7364             static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
7365         }
7366 
7367         // @property void modPropSetterOnly(string);
7368         // @property void modPropSetterOnly(int);
7369         {
7370             static assert( is(SymbolType!modPropSetterOnly == ToFunctionType!(void function(string) @property)));
7371             static assert(!__traits(compiles, PropertyType!modPropSetterOnly));
7372             static assert(!__traits(compiles, typeof(modPropSetterOnly)));
7373 
7374             alias overloads = __traits(getOverloads, module_, "modPropSetterOnly");
7375             static assert(overloads.length == 2);
7376 
7377             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string) @property)));
7378             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7379             static assert(!__traits(compiles, typeof(overloads[0])));
7380 
7381             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int) @property)));
7382             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7383             static assert(!__traits(compiles, typeof(overloads[1])));
7384         }
7385 
7386         // int function() @property modGetterFirstFuncPtr();
7387         // void modGetterFirstFuncPtr(int function() @property);
7388         {
7389             static assert( is(SymbolType!modGetterFirstFuncPtr ==
7390                               ToFunctionType!(int function() @property function())));
7391             static assert( is(PropertyType!modGetterFirstFuncPtr == int function() @property));
7392             static assert( is(typeof(modGetterFirstFuncPtr) == SymbolType!modGetterFirstFuncPtr));
7393 
7394             alias overloads = __traits(getOverloads, module_, "modGetterFirstFuncPtr");
7395             static assert(overloads.length == 2);
7396 
7397             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function() @property function())));
7398             static assert( is(PropertyType!(overloads[0]) == int function() @property));
7399             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7400 
7401             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int function() @property))));
7402             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7403             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7404         }
7405 
7406         // void modSetterFirstFuncPtr(int function() @property);
7407         // int function() @property modSetterFirstFuncPtr();
7408         {
7409             static assert( is(SymbolType!modSetterFirstFuncPtr ==
7410                               ToFunctionType!(void function(int function() @property))));
7411             static assert( is(PropertyType!modSetterFirstFuncPtr == int function() @property));
7412             static assert( is(typeof(modSetterFirstFuncPtr) == SymbolType!modSetterFirstFuncPtr));
7413 
7414             alias overloads = __traits(getOverloads, module_, "modSetterFirstFuncPtr");
7415             static assert(overloads.length == 2);
7416 
7417             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int function() @property))));
7418             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7419             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7420 
7421             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property function())));
7422             static assert( is(PropertyType!(overloads[1]) == int function() @property));
7423             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7424         }
7425 
7426         // int function() @property modPropGetterFirstFuncPtr() @property;
7427         // void modPropGetterFirstFuncPtr(int function() @property) @property;
7428         {
7429             static assert( is(SymbolType!modPropGetterFirstFuncPtr ==
7430                               ToFunctionType!(int function() @property function() @property)));
7431             static assert( is(PropertyType!modPropGetterFirstFuncPtr == int function() @property));
7432             static assert( is(typeof(modPropGetterFirstFuncPtr) == PropertyType!modPropGetterFirstFuncPtr));
7433 
7434             alias overloads = __traits(getOverloads, module_, "modPropGetterFirstFuncPtr");
7435             static assert(overloads.length == 2);
7436 
7437             static assert( is(SymbolType!(overloads[0]) ==
7438                               ToFunctionType!(int function() @property function() @property)));
7439             static assert( is(PropertyType!(overloads[0]) == int function() @property));
7440             static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
7441 
7442             static assert( is(SymbolType!(overloads[1]) ==
7443                               ToFunctionType!(void function(int function() @property) @property)));
7444             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7445             static assert(!__traits(compiles, typeof((overloads[1]))));
7446         }
7447 
7448         // void modPropSetterFirstFuncPtr(int function() @property) @property;
7449         // int function() @property modPropSetterFirstFuncPtr() @property;
7450         {
7451             static assert( is(SymbolType!modPropSetterFirstFuncPtr ==
7452                               ToFunctionType!(void function(int function() @property) @property)));
7453             static assert( is(PropertyType!modPropSetterFirstFuncPtr == int function() @property));
7454             static assert( is(typeof(modPropSetterFirstFuncPtr) == PropertyType!modPropSetterFirstFuncPtr));
7455 
7456             alias overloads = __traits(getOverloads, module_, "modPropSetterFirstFuncPtr");
7457             static assert(overloads.length == 2);
7458 
7459             static assert( is(SymbolType!(overloads[0]) ==
7460                               ToFunctionType!(void function(int function() @property) @property)));
7461             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7462             static assert(!__traits(compiles, typeof(overloads[0])));
7463 
7464             static assert( is(SymbolType!(overloads[1]) ==
7465                               ToFunctionType!(int function() @property function() @property)));
7466             static assert( is(PropertyType!(overloads[1]) == int function() @property));
7467             static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
7468         }
7469     }
7470 
7471     {
7472         static struct S
7473         {
7474             int[] arr1;
7475             immutable bool[] arr2;
7476 
7477             void foo();
7478             static void bar();
7479 
7480             long bob();
7481             void sally(long);
7482 
7483             @property long propGetter();
7484             @property void propSetter(int[]);
7485 
7486             static @property long staticPropGetter();
7487             static @property void staticPropSetter(int[]);
7488 
7489             void func1();
7490             void func1(int[]);
7491             long func1(int[], long);
7492 
7493             long func2();
7494             long func2(int[]);
7495             int[] func2(int[], long);
7496 
7497             void func3(long*);
7498             void func3(real);
7499             int[] func3(long a = 0);
7500 
7501             long getterFirst();
7502             void getterFirst(long);
7503 
7504             void setterFirst(long);
7505             long setterFirst();
7506 
7507             void setterOnly(int[]);
7508             void setterOnly(long);
7509 
7510             static long staticGetterFirst();
7511             static void staticGetterFirst(long);
7512 
7513             static void staticSetterFirst(long);
7514             static long staticSetterFirst();
7515 
7516             static void staticSetterOnly(int[]);
7517             static void staticSetterOnly(long);
7518 
7519             @property long propGetterFirst();
7520             @property void propGetterFirst(long);
7521 
7522             @property void propSetterFirst(long);
7523             @property long propSetterFirst();
7524 
7525             @property void propSetterOnly(int[]);
7526             @property void propSetterOnly(long);
7527 
7528             static @property long staticPropGetterFirst();
7529             static @property void staticPropGetterFirst(long);
7530 
7531             static @property void staticPropSetterFirst(long);
7532             static @property long staticPropSetterFirst();
7533 
7534             static @property void staticPropSetterOnly(int[]);
7535             static @property void staticPropSetterOnly(long);
7536 
7537             long function() @property getterFirstFuncPtr();
7538             void getterFirstFuncPtr(long function() @property);
7539 
7540             void setterFirstFuncPtr(long function() @property);
7541             long function() @property setterFirstFuncPtr();
7542 
7543             long function() @property propGetterFirstFuncPtr() @property;
7544             void propGetterFirstFuncPtr(long function() @property) @property;
7545 
7546             void propSetterFirstFuncPtr(long function() @property) @property;
7547             long function() @property propSetterFirstFuncPtr() @property;
7548 
7549             static long delegate() @property staticGetterFirstDel();
7550             static void staticGetterFirstDel(long delegate() @property);
7551 
7552             static void staticSetterFirstDel(long delegate() @property);
7553             static long delegate() @property staticSetterFirstDel();
7554 
7555             static long delegate() @property staticPropGetterFirstDel() @property;
7556             static void staticPropGetterFirstDel(long delegate() @property) @property;
7557 
7558             static void staticPropSetterFirstDel(long delegate() @property) @property;
7559             static long delegate() @property staticPropSetterFirstDel() @property;
7560         }
7561 
7562         // int[] arr1;
7563         // immutable bool[] arr2;
7564         static assert( is(SymbolType!(S.arr1) == int[]));
7565         static assert( is(PropertyType!(S.arr1) == int[]));
7566         static assert( is(typeof(S.arr1) == int[]));
7567 
7568         static assert( is(SymbolType!(S.arr2) == immutable bool[]));
7569         static assert( is(PropertyType!(S.arr2) == immutable bool[]));
7570         static assert( is(typeof(S.arr2) == immutable bool[]));
7571 
7572         // void foo();
7573         static assert( is(SymbolType!(S.foo) == function));
7574         static assert( is(SymbolType!(S.foo) == ToFunctionType!(void function())));
7575         static assert(!__traits(compiles, PropertyType!(S.foo)));
7576         static assert( is(typeof(S.foo) == SymbolType!(S.foo)));
7577 
7578         //static void bar();
7579         static assert( is(SymbolType!(S.bar) == function));
7580         static assert( is(SymbolType!(S.bar) == ToFunctionType!(void function())));
7581         static assert(!__traits(compiles, PropertyType!(S.bar)));
7582         static assert( is(typeof(S.bar) == SymbolType!(S.bar)));
7583 
7584         // long bob();
7585         static assert( is(SymbolType!(S.bob) == function));
7586         static assert( is(SymbolType!(S.bob) == ToFunctionType!(long function())));
7587         static assert( is(PropertyType!(S.bob) == long));
7588         static assert( is(typeof(S.bob) == SymbolType!(S.bob)));
7589 
7590         // void sally(long);
7591         static assert( is(SymbolType!(S.sally) == function));
7592         static assert( is(SymbolType!(S.sally) == ToFunctionType!(void function(long))));
7593         static assert(!__traits(compiles, PropertyType!(S.sally)));
7594         static assert( is(typeof(S.sally) == SymbolType!(S.sally)));
7595 
7596         // @property long propGetter();
7597         static assert( is(SymbolType!(S.propGetter) == function));
7598         static assert( is(SymbolType!(S.propGetter) == ToFunctionType!(long function() @property)));
7599         static assert( is(PropertyType!(S.propGetter) == long));
7600         static assert( is(typeof(S.propGetter) == PropertyType!(S.propGetter)));
7601 
7602         // @property void propSetter(int[]);
7603         static assert( is(SymbolType!(S.propSetter) == function));
7604         static assert( is(SymbolType!(S.propSetter) == ToFunctionType!(void function(int[]) @property)));
7605         static assert(!__traits(compiles, PropertyType!(S.propSetter)));
7606         static assert(!__traits(compiles, typeof(S.propSetter)));
7607 
7608         // static @property long staticPropGetter();
7609         static assert( is(SymbolType!(S.staticPropGetter) == function));
7610         static assert( is(SymbolType!(S.staticPropGetter) == ToFunctionType!(long function() @property)));
7611         static assert( is(PropertyType!(S.staticPropGetter) == long));
7612         static assert( is(typeof(S.staticPropGetter) == PropertyType!(S.staticPropGetter)));
7613 
7614         // static @property void staticPropSetter(int[]);
7615         static assert( is(SymbolType!(S.staticPropSetter) == function));
7616         static assert( is(SymbolType!(S.staticPropSetter) == ToFunctionType!(void function(int[]) @property)));
7617         static assert(!__traits(compiles, PropertyType!(S.staticPropSetter)));
7618         static assert(!__traits(compiles, typeof(S.staticPropSetter)));
7619 
7620         // void func1();
7621         // void func1(int[]);
7622         // long func1(int[], long);
7623         {
7624             static assert( is(SymbolType!(S.func1) == ToFunctionType!(void function())));
7625             static assert(!__traits(compiles, PropertyType!(S.func1)));
7626             static assert( is(typeof((S.func1)) == SymbolType!(S.func1)));
7627 
7628             alias overloads = __traits(getOverloads, S, "func1");
7629             static assert(overloads.length == 3);
7630 
7631             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function())));
7632             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7633             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7634 
7635             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int[]))));
7636             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7637             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7638 
7639             static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(long function(int[], long))));
7640             static assert(!__traits(compiles, PropertyType!(overloads[2])));
7641             static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2])));
7642         }
7643 
7644         // long func2();
7645         // long func2(int[]);
7646         // int[] func2(int[], long);
7647         {
7648             static assert( is(SymbolType!(S.func2) == ToFunctionType!(long function())));
7649             static assert( is(PropertyType!(S.func2) == long));
7650             static assert( is(typeof((S.func2)) == SymbolType!(S.func2)));
7651 
7652             alias overloads = __traits(getOverloads, S, "func2");
7653             static assert(overloads.length == 3);
7654 
7655             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function())));
7656             static assert( is(PropertyType!(overloads[0]) == long));
7657             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7658 
7659             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function(int[]))));
7660             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7661             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7662 
7663             static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(int[] function(int[], long))));
7664             static assert(!__traits(compiles, PropertyType!(overloads[2])));
7665             static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2])));
7666         }
7667 
7668         // void func3(long*);
7669         // void func3(real);
7670         // int[] func3(long a = 0);
7671         {
7672             static assert( is(SymbolType!(S.func3) == ToFunctionType!(void function(long*))));
7673             static assert( is(PropertyType!(S.func3) == int[]));
7674             static assert( is(typeof((S.func3)) == SymbolType!(S.func3)));
7675 
7676             alias overloads = __traits(getOverloads, S, "func3");
7677             static assert(overloads.length == 3);
7678 
7679             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long*))));
7680             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7681             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7682 
7683             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(real))));
7684             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7685             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7686 
7687             static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(int[] function(long))));
7688             static assert( is(PropertyType!(overloads[2]) == int[]));
7689             static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2])));
7690         }
7691 
7692         // long getterFirst();
7693         // void getterFirst(long);
7694         {
7695             static assert( is(SymbolType!(S.getterFirst) == ToFunctionType!(long function())));
7696             static assert( is(PropertyType!(S.getterFirst) == long));
7697             static assert( is(typeof((S.getterFirst)) == SymbolType!(S.getterFirst)));
7698 
7699             alias overloads = __traits(getOverloads, S, "getterFirst");
7700             static assert(overloads.length == 2);
7701 
7702             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function())));
7703             static assert( is(PropertyType!(overloads[0]) == long));
7704             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7705 
7706             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long))));
7707             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7708             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7709         }
7710 
7711         // void setterFirst(long);
7712         // long setterFirst();
7713         {
7714             static assert( is(SymbolType!(S.setterFirst) == ToFunctionType!(void function(long))));
7715             static assert( is(PropertyType!(S.setterFirst) == long));
7716             static assert( is(typeof((S.setterFirst)) == SymbolType!(S.setterFirst)));
7717 
7718             alias overloads = __traits(getOverloads, S, "setterFirst");
7719             static assert(overloads.length == 2);
7720 
7721             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long))));
7722             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7723             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7724 
7725             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function())));
7726             static assert( is(PropertyType!(overloads[1]) == long));
7727             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7728         }
7729 
7730         // void setterOnly(int[]);
7731         // void setterOnly(long);
7732         {
7733             static assert( is(SymbolType!(S.setterOnly) == ToFunctionType!(void function(int[]))));
7734             static assert(!__traits(compiles, PropertyType!(S.setterOnly)));
7735             static assert( is(typeof((S.setterOnly)) == SymbolType!(S.setterOnly)));
7736 
7737             alias overloads = __traits(getOverloads, S, "setterOnly");
7738             static assert(overloads.length == 2);
7739 
7740             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int[]))));
7741             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7742             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7743 
7744             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long))));
7745             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7746             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7747         }
7748 
7749         // long staticGetterFirst();
7750         // void staticGetterFirst(long);
7751         {
7752             static assert( is(SymbolType!(S.staticGetterFirst) == ToFunctionType!(long function())));
7753             static assert( is(PropertyType!(S.staticGetterFirst) == long));
7754             static assert( is(typeof((S.staticGetterFirst)) == SymbolType!(S.staticGetterFirst)));
7755 
7756             alias overloads = __traits(getOverloads, S, "staticGetterFirst");
7757             static assert(overloads.length == 2);
7758 
7759             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function())));
7760             static assert( is(PropertyType!(overloads[0]) == long));
7761             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7762 
7763             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long))));
7764             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7765             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7766         }
7767 
7768         // void staticSetterFirst(long);
7769         // long staticSetterFirst();
7770         {
7771             static assert( is(SymbolType!(S.staticSetterFirst) == ToFunctionType!(void function(long))));
7772             static assert( is(PropertyType!(S.staticSetterFirst) == long));
7773             static assert( is(typeof((S.staticSetterFirst)) == SymbolType!(S.staticSetterFirst)));
7774 
7775             alias overloads = __traits(getOverloads, S, "staticSetterFirst");
7776             static assert(overloads.length == 2);
7777 
7778             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long))));
7779             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7780             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7781 
7782             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function())));
7783             static assert( is(PropertyType!(overloads[1]) == long));
7784             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7785         }
7786 
7787         // void staticSetterOnly(int[]);
7788         // void staticSetterOnly(long);
7789         {
7790             static assert( is(SymbolType!(S.staticSetterOnly) == ToFunctionType!(void function(int[]))));
7791             static assert(!__traits(compiles, PropertyType!(S.staticSetterOnly)));
7792             static assert( is(typeof((S.staticSetterOnly)) == SymbolType!(S.staticSetterOnly)));
7793 
7794             alias overloads = __traits(getOverloads, S, "staticSetterOnly");
7795             static assert(overloads.length == 2);
7796 
7797             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int[]))));
7798             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7799             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7800 
7801             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long))));
7802             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7803             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7804         }
7805 
7806         // @property long propGetterFirst();
7807         // @property void propGetterFirst(long);
7808         {
7809             static assert( is(SymbolType!(S.propGetterFirst) == ToFunctionType!(long function() @property)));
7810             static assert( is(PropertyType!(S.propGetterFirst) == long));
7811             static assert( is(typeof((S.propGetterFirst)) == PropertyType!(S.propGetterFirst)));
7812 
7813             alias overloads = __traits(getOverloads, S, "propGetterFirst");
7814             static assert(overloads.length == 2);
7815 
7816             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function() @property)));
7817             static assert( is(PropertyType!(overloads[0]) == long));
7818             static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
7819 
7820             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long) @property)));
7821             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7822             static assert(!__traits(compiles, typeof((overloads[1]))));
7823         }
7824 
7825         // @property void propSetterFirst(long);
7826         // @property long propSetterFirst();
7827         {
7828             static assert( is(SymbolType!(S.propSetterFirst) == ToFunctionType!(void function(long) @property)));
7829             static assert( is(PropertyType!(S.propSetterFirst) == long));
7830             static assert( is(typeof((S.propSetterFirst)) == PropertyType!(S.propSetterFirst)));
7831 
7832             alias overloads = __traits(getOverloads, S, "propSetterFirst");
7833             static assert(overloads.length == 2);
7834 
7835             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long) @property)));
7836             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7837             static assert(!__traits(compiles, typeof(overloads[0])));
7838 
7839             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function() @property)));
7840             static assert( is(PropertyType!(overloads[1]) == long));
7841             static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
7842         }
7843 
7844         // @property void propSetterOnly(int[]);
7845         // @property void propSetterOnly(long);
7846         {
7847             static assert( is(SymbolType!(S.propSetterOnly) == ToFunctionType!(void function(int[]) @property)));
7848             static assert(!__traits(compiles, PropertyType!(S.propSetterOnly)));
7849             static assert(!__traits(compiles, typeof((S.propSetterOnly))));
7850 
7851             alias overloads = __traits(getOverloads, S, "propSetterOnly");
7852             static assert(overloads.length == 2);
7853 
7854             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int[]) @property)));
7855             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7856             static assert(!__traits(compiles, typeof(overloads[0])));
7857 
7858             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long) @property)));
7859             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7860             static assert(!__traits(compiles, typeof(overloads[1])));
7861         }
7862 
7863         // @property long staticPropGetterFirst();
7864         // @property void staticPropGetterFirst(long);
7865         {
7866             static assert( is(SymbolType!(S.staticPropGetterFirst) == ToFunctionType!(long function() @property)));
7867             static assert( is(PropertyType!(S.staticPropGetterFirst) == long));
7868             static assert( is(typeof((S.staticPropGetterFirst)) == PropertyType!(S.staticPropGetterFirst)));
7869 
7870             alias overloads = __traits(getOverloads, S, "staticPropGetterFirst");
7871             static assert(overloads.length == 2);
7872 
7873             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function() @property)));
7874             static assert( is(PropertyType!(overloads[0]) == long));
7875             static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
7876 
7877             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long) @property)));
7878             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7879             static assert(!__traits(compiles, typeof((overloads[1]))));
7880         }
7881 
7882         // @property void staticPropSetterFirst(long);
7883         // @property long staticPropSetterFirst();
7884         {
7885             static assert( is(SymbolType!(S.staticPropSetterFirst) == ToFunctionType!(void function(long) @property)));
7886             static assert( is(PropertyType!(S.staticPropSetterFirst) == long));
7887             static assert( is(typeof((S.staticPropSetterFirst)) == PropertyType!(S.staticPropSetterFirst)));
7888 
7889             alias overloads = __traits(getOverloads, S, "staticPropSetterFirst");
7890             static assert(overloads.length == 2);
7891 
7892             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long) @property)));
7893             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7894             static assert(!__traits(compiles, typeof(overloads[0])));
7895 
7896             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function() @property)));
7897             static assert( is(PropertyType!(overloads[1]) == long));
7898             static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
7899         }
7900 
7901         // @property void staticPropSetterOnly(int[]);
7902         // @property void staticPropSetterOnly(long);
7903         {
7904             static assert( is(SymbolType!(S.staticPropSetterOnly) == ToFunctionType!(void function(int[]) @property)));
7905             static assert(!__traits(compiles, PropertyType!(S.staticPropSetterOnly)));
7906             static assert(!__traits(compiles, typeof((S.staticPropSetterOnly))));
7907 
7908             alias overloads = __traits(getOverloads, S, "staticPropSetterOnly");
7909             static assert(overloads.length == 2);
7910 
7911             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int[]) @property)));
7912             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7913             static assert(!__traits(compiles, typeof(overloads[0])));
7914 
7915             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long) @property)));
7916             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7917             static assert(!__traits(compiles, typeof(overloads[1])));
7918         }
7919 
7920         // long function() @property getterFirstFuncPtr();
7921         // void getterFirstFuncPtr(long function() @property);
7922         {
7923             static assert( is(SymbolType!(S.getterFirstFuncPtr) ==
7924                               ToFunctionType!(long function() @property function())));
7925             static assert( is(PropertyType!(S.getterFirstFuncPtr) == long function() @property));
7926             static assert( is(typeof((S.getterFirstFuncPtr)) == SymbolType!(S.getterFirstFuncPtr)));
7927 
7928             alias overloads = __traits(getOverloads, S, "getterFirstFuncPtr");
7929             static assert(overloads.length == 2);
7930 
7931             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function() @property function())));
7932             static assert( is(PropertyType!(overloads[0]) == long function() @property));
7933             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7934 
7935             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long function() @property))));
7936             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7937             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7938         }
7939 
7940         // void setterFirstFuncPtr(long function() @property);
7941         // long function() @property setterFirstFuncPtr();
7942         {
7943             static assert( is(SymbolType!(S.setterFirstFuncPtr) ==
7944                               ToFunctionType!(void function(long function() @property))));
7945             static assert( is(PropertyType!(S.setterFirstFuncPtr) == long function() @property));
7946             static assert( is(typeof((S.setterFirstFuncPtr)) == SymbolType!(S.setterFirstFuncPtr)));
7947 
7948             alias overloads = __traits(getOverloads, S, "setterFirstFuncPtr");
7949             static assert(overloads.length == 2);
7950 
7951             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long function() @property))));
7952             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7953             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7954 
7955             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function() @property function())));
7956             static assert( is(PropertyType!(overloads[1]) == long function() @property));
7957             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7958         }
7959 
7960         // long function() @property propGetterFirstFuncPtr() @property;
7961         // void propGetterFirstFuncPtr(long function() @property) @property;
7962         {
7963             static assert( is(SymbolType!(S.propGetterFirstFuncPtr) ==
7964                               ToFunctionType!(long function() @property function() @property)));
7965             static assert( is(PropertyType!(S.propGetterFirstFuncPtr) == long function() @property));
7966             static assert( is(typeof((S.propGetterFirstFuncPtr)) == PropertyType!(S.propGetterFirstFuncPtr)));
7967 
7968             alias overloads = __traits(getOverloads, S, "propGetterFirstFuncPtr");
7969             static assert(overloads.length == 2);
7970 
7971             static assert( is(SymbolType!(overloads[0]) ==
7972                               ToFunctionType!(long function() @property function() @property)));
7973             static assert( is(PropertyType!(overloads[0]) == long function() @property));
7974             static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
7975 
7976             static assert( is(SymbolType!(overloads[1]) ==
7977                               ToFunctionType!(void function(long function() @property) @property)));
7978             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7979             static assert(!__traits(compiles, typeof((overloads[1]))));
7980         }
7981 
7982         // void propSetterFirstFuncPtr(long function() @property) @property;
7983         // long function() @property propSetterFirstFuncPtr() @property;
7984         {
7985             static assert( is(SymbolType!(S.propSetterFirstFuncPtr) ==
7986                               ToFunctionType!(void function(long function() @property) @property)));
7987             static assert( is(PropertyType!(S.propSetterFirstFuncPtr) == long function() @property));
7988             static assert( is(typeof((S.propSetterFirstFuncPtr)) == PropertyType!(S.propSetterFirstFuncPtr)));
7989 
7990             alias overloads = __traits(getOverloads, S, "propSetterFirstFuncPtr");
7991             static assert(overloads.length == 2);
7992 
7993             static assert( is(SymbolType!(overloads[0]) ==
7994                               ToFunctionType!(void function(long function() @property) @property)));
7995             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7996             static assert(!__traits(compiles, typeof(overloads[0])));
7997 
7998             static assert( is(SymbolType!(overloads[1]) ==
7999                               ToFunctionType!(long function() @property function() @property)));
8000             static assert( is(PropertyType!(overloads[1]) == long function() @property));
8001             static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
8002         }
8003 
8004         // long function() @property staticGetterFirstDel();
8005         // void staticGetterFirstDel(long function() @property);
8006         {
8007             static assert( is(SymbolType!(S.staticGetterFirstDel) ==
8008                               ToFunctionType!(long delegate() @property function())));
8009             static assert( is(PropertyType!(S.staticGetterFirstDel) == long delegate() @property));
8010             static assert( is(typeof((S.staticGetterFirstDel)) == SymbolType!(S.staticGetterFirstDel)));
8011 
8012             alias overloads = __traits(getOverloads, S, "staticGetterFirstDel");
8013             static assert(overloads.length == 2);
8014 
8015             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long delegate() @property function())));
8016             static assert( is(PropertyType!(overloads[0]) == long delegate() @property));
8017             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8018 
8019             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long delegate() @property))));
8020             static assert(!__traits(compiles, PropertyType!(overloads[1])));
8021             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8022         }
8023 
8024         // void setterFirstDel(long function() @property);
8025         // long function() @property setterFirstDel();
8026         {
8027             static assert( is(SymbolType!(S.staticSetterFirstDel) ==
8028                               ToFunctionType!(void function(long delegate() @property))));
8029             static assert( is(PropertyType!(S.staticSetterFirstDel) == long delegate() @property));
8030             static assert( is(typeof((S.staticSetterFirstDel)) == SymbolType!(S.staticSetterFirstDel)));
8031 
8032             alias overloads = __traits(getOverloads, S, "staticSetterFirstDel");
8033             static assert(overloads.length == 2);
8034 
8035             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long delegate() @property))));
8036             static assert(!__traits(compiles, PropertyType!(overloads[0])));
8037             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8038 
8039             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long delegate() @property function())));
8040             static assert( is(PropertyType!(overloads[1]) == long delegate() @property));
8041             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8042         }
8043 
8044         // long function() @property staticPropGetterFirstDel() @property;
8045         // void staticPropGetterFirstDel(long function() @property) @property;
8046         {
8047             static assert( is(SymbolType!(S.staticPropGetterFirstDel) ==
8048                               ToFunctionType!(long delegate() @property function() @property)));
8049             static assert( is(PropertyType!(S.staticPropGetterFirstDel) == long delegate() @property));
8050             static assert( is(typeof((S.staticPropGetterFirstDel)) == PropertyType!(S.staticPropGetterFirstDel)));
8051 
8052             alias overloads = __traits(getOverloads, S, "staticPropGetterFirstDel");
8053             static assert(overloads.length == 2);
8054 
8055             static assert( is(SymbolType!(overloads[0]) ==
8056                               ToFunctionType!(long delegate() @property function() @property)));
8057             static assert( is(PropertyType!(overloads[0]) == long delegate() @property));
8058             static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
8059 
8060             static assert( is(SymbolType!(overloads[1]) ==
8061                               ToFunctionType!(void function(long delegate() @property) @property)));
8062             static assert(!__traits(compiles, PropertyType!(overloads[1])));
8063             static assert(!__traits(compiles, typeof((overloads[1]))));
8064         }
8065 
8066         // void propSetterFirstDel(long function() @property) @property;
8067         // long function() @property propSetterFirstDel() @property;
8068         {
8069             static assert( is(SymbolType!(S.staticPropSetterFirstDel) ==
8070                               ToFunctionType!(void function(long delegate() @property) @property)));
8071             static assert( is(PropertyType!(S.staticPropSetterFirstDel) == long delegate() @property));
8072             static assert( is(typeof((S.staticPropSetterFirstDel)) == PropertyType!(S.staticPropSetterFirstDel)));
8073 
8074             alias overloads = __traits(getOverloads, S, "staticPropSetterFirstDel");
8075             static assert(overloads.length == 2);
8076 
8077             static assert( is(SymbolType!(overloads[0]) ==
8078                               ToFunctionType!(void function(long delegate() @property) @property)));
8079             static assert(!__traits(compiles, PropertyType!(overloads[0])));
8080             static assert(!__traits(compiles, typeof(overloads[0])));
8081 
8082             static assert( is(SymbolType!(overloads[1]) ==
8083                               ToFunctionType!(long delegate() @property function() @property)));
8084             static assert( is(PropertyType!(overloads[1]) == long delegate() @property));
8085             static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
8086         }
8087     }
8088     {
8089         static interface I
8090         {
8091             void foo();
8092             static void bar();
8093 
8094             int func1();
8095             void func1(int);
8096 
8097             void func2(int);
8098             int func2();
8099 
8100             @property void prop1(int);
8101             @property int prop1();
8102 
8103             @property int prop2();
8104             @property void prop2(int);
8105 
8106             static @property string staticProp();
8107             static @property void staticProp(real);
8108 
8109             @property void extraProp(string);
8110 
8111             int defaultArg1(string str = "foo");
8112             void defaultArg1(int, string str = "foo");
8113 
8114             void defaultArg2(int, string str = "foo");
8115             int defaultArg2(string str = "foo");
8116 
8117             @property int defaultArgProp1(string str = "foo");
8118             @property void defaultArgProp1(int, string str = "foo");
8119 
8120             @property void defaultArgProp2(int, string str = "foo");
8121             @property int defaultArgProp2(string str = "foo");
8122 
8123             string defaultArgInDerived1(int);
8124             void defaultArgInDerived1(string, int);
8125 
8126             void defaultArgInDerived2(string, int);
8127             string defaultArgInDerived2(int);
8128 
8129             @property string defaultArgInDerivedProp1(int);
8130             @property void defaultArgInDerivedProp1(string, int);
8131 
8132             @property void defaultArgInDerivedProp2(string, int);
8133             @property string defaultArgInDerivedProp2(int);
8134         }
8135 
8136         {
8137             // void foo()
8138             static assert( is(SymbolType!(I.foo) == ToFunctionType!(void function())));
8139             static assert(!__traits(compiles, PropertyType!(I.foo)));
8140             static assert( is(typeof(I.foo) == SymbolType!(I.foo)));
8141 
8142             // static void bar()
8143             static assert( is(SymbolType!(I.bar) == ToFunctionType!(void function())));
8144             static assert(!__traits(compiles, PropertyType!(I.bar)));
8145             static assert( is(typeof(I.bar) == SymbolType!(I.bar)));
8146 
8147             // int func1();
8148             // void func1(int);
8149             {
8150                 static assert( is(SymbolType!(I.func1) == ToFunctionType!(int function())));
8151                 static assert( is(PropertyType!(I.func1) == int));
8152                 static assert( is(typeof(I.func1) == SymbolType!(I.func1)));
8153 
8154                 alias overloads = __traits(getOverloads, I, "func1");
8155                 static assert(overloads.length == 2);
8156 
8157                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function())));
8158                 static assert( is(PropertyType!(overloads[0]) == int));
8159                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8160 
8161                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int))));
8162                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8163                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8164             }
8165 
8166             // void func2(int);
8167             // int func2();
8168             {
8169                 static assert( is(SymbolType!(I.func2) == ToFunctionType!(void function(int))));
8170                 static assert( is(PropertyType!(I.func2) == int));
8171                 static assert( is(typeof(I.func2) == SymbolType!(I.func2)));
8172 
8173                 alias overloads = __traits(getOverloads, I, "func2");
8174                 static assert(overloads.length == 2);
8175 
8176                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int))));
8177                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8178                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8179 
8180                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function())));
8181                 static assert( is(PropertyType!(overloads[1]) == int));
8182                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8183             }
8184 
8185             // @property void prop1(int);
8186             // @property int prop1();
8187             {
8188                 static assert( is(SymbolType!(I.prop1) == ToFunctionType!(void function(int) @property)));
8189                 static assert( is(PropertyType!(I.prop1) == int));
8190                 static assert( is(typeof(I.prop1) == PropertyType!(I.prop1)));
8191 
8192                 alias overloads = __traits(getOverloads, I, "prop1");
8193                 static assert(overloads.length == 2);
8194 
8195                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property)));
8196                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8197                 static assert(!__traits(compiles, typeof(overloads[0])));
8198 
8199                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property)));
8200                 static assert( is(PropertyType!(overloads[1]) == int));
8201                 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
8202             }
8203 
8204             // @property int prop2();
8205             // @property void prop2(int);
8206             {
8207                 static assert( is(SymbolType!(I.prop2) == ToFunctionType!(int function() @property)));
8208                 static assert( is(PropertyType!(I.prop2) == int));
8209                 static assert( is(typeof(I.prop2) == PropertyType!(I.prop2)));
8210 
8211                 alias overloads = __traits(getOverloads, I, "prop2");
8212                 static assert(overloads.length == 2);
8213 
8214                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function() @property)));
8215                 static assert( is(PropertyType!(overloads[0]) == int));
8216                 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
8217 
8218                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int) @property)));
8219                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8220                 static assert(!__traits(compiles, typeof(overloads[1])));
8221             }
8222 
8223             // static @property string staticProp();
8224             // static @property void staticProp(real);
8225             {
8226                 static assert( is(SymbolType!(I.staticProp) == ToFunctionType!(string function() @property)));
8227                 static assert( is(PropertyType!(I.staticProp) == string));
8228                 static assert( is(typeof(I.staticProp) == PropertyType!(I.staticProp)));
8229 
8230                 alias overloads = __traits(getOverloads, I, "staticProp");
8231                 static assert(overloads.length == 2);
8232 
8233                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function() @property)));
8234                 static assert( is(PropertyType!(overloads[0]) == string));
8235                 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
8236 
8237                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(real) @property)));
8238                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8239                 static assert(!__traits(compiles, typeof(overloads[1])));
8240             }
8241 
8242             // @property void extraProp(string);
8243             {
8244                 static assert( is(SymbolType!(I.extraProp) == ToFunctionType!(void function(string) @property)));
8245                 static assert(!__traits(compiles, PropertyType!(I.extraProp)));
8246                 static assert(!__traits(compiles, typeof(I.extraProp)));
8247 
8248                 alias overloads = __traits(getOverloads, I, "extraProp");
8249                 static assert(overloads.length == 1);
8250 
8251                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string) @property)));
8252                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8253                 static assert(!__traits(compiles, typeof(overloads[0])));
8254             }
8255 
8256             // int defaultArg1(string str = "foo");
8257             // void defaultArg1(int, string str = "foo");
8258             {
8259                 static assert( is(SymbolType!(I.defaultArg1) == ToFunctionType!(int function(string))));
8260                 static assert( is(PropertyType!(I.defaultArg1) == int));
8261                 static assert( is(typeof(I.defaultArg1) == SymbolType!(I.defaultArg1)));
8262 
8263                 alias overloads = __traits(getOverloads, I, "defaultArg1");
8264                 static assert(overloads.length == 2);
8265 
8266                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string))));
8267                 static assert( is(PropertyType!(overloads[0]) == int));
8268                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8269 
8270                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string))));
8271                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8272                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8273             }
8274 
8275             // void defaultArg2(int, string str = "foo");
8276             // int defaultArg2(string str = "foo");
8277             {
8278                 static assert( is(SymbolType!(I.defaultArg2) == ToFunctionType!(void function(int, string))));
8279                 static assert( is(PropertyType!(I.defaultArg2) == int));
8280                 static assert( is(typeof(I.defaultArg2) == SymbolType!(I.defaultArg2)));
8281 
8282                 alias overloads = __traits(getOverloads, I, "defaultArg2");
8283                 static assert(overloads.length == 2);
8284 
8285                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string))));
8286                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8287                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8288 
8289                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string))));
8290                 static assert( is(PropertyType!(overloads[1]) == int));
8291                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8292             }
8293 
8294             // @property int defaultArgProp1(string str = "foo");
8295             // @property void defaultArgProp1(int, string str = "foo");
8296             {
8297                 static assert( is(SymbolType!(I.defaultArgProp1) == ToFunctionType!(int function(string) @property)));
8298                 static assert( is(PropertyType!(I.defaultArgProp1) == int));
8299                 static assert( is(typeof(I.defaultArgProp1) == PropertyType!(I.defaultArgProp1)));
8300 
8301                 alias overloads = __traits(getOverloads, I, "defaultArgProp1");
8302                 static assert(overloads.length == 2);
8303 
8304                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string) @property)));
8305                 static assert( is(PropertyType!(overloads[0]) == int));
8306                 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
8307 
8308                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string) @property)));
8309                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8310                 static assert(!__traits(compiles, typeof(overloads[1])));
8311             }
8312 
8313             // @property void defaultArgProp2(int, string str = "foo");
8314             // @property int defaultArgProp2(string str = "foo");
8315             {
8316                 static assert( is(SymbolType!(I.defaultArgProp2) ==
8317                                   ToFunctionType!(void function(int, string) @property)));
8318                 static assert( is(PropertyType!(I.defaultArgProp2) == int));
8319                 static assert( is(typeof(I.defaultArgProp2) == PropertyType!(I.defaultArgProp2)));
8320 
8321                 alias overloads = __traits(getOverloads, I, "defaultArgProp2");
8322                 static assert(overloads.length == 2);
8323 
8324                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string) @property)));
8325                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8326                 static assert(!__traits(compiles, typeof(overloads[0])));
8327 
8328                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string) @property)));
8329                 static assert( is(PropertyType!(overloads[1]) == int));
8330                 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
8331             }
8332 
8333             // string defaultArgInDerived1(int);
8334             // void defaultArgInDerived1(string, int);
8335             {
8336                 static assert( is(SymbolType!(I.defaultArgInDerived1) == ToFunctionType!(string function(int))));
8337                 static assert(!__traits(compiles, PropertyType!(I.defaultArgInDerived1)));
8338                 static assert( is(typeof(I.defaultArgInDerived1) == SymbolType!(I.defaultArgInDerived1)));
8339 
8340                 alias overloads = __traits(getOverloads, I, "defaultArgInDerived1");
8341                 static assert(overloads.length == 2);
8342 
8343                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int))));
8344                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8345                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8346 
8347                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int))));
8348                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8349                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8350             }
8351 
8352             // void defaultArgInDerived2(string, int);
8353             // string defaultArgInDerived2(int);
8354             {
8355                 static assert( is(SymbolType!(I.defaultArgInDerived2) == ToFunctionType!(void function(string, int))));
8356                 static assert(!__traits(compiles, PropertyType!(I.defaultArgInDerived2)));
8357                 static assert( is(typeof(I.defaultArgInDerived2) == SymbolType!(I.defaultArgInDerived2)));
8358 
8359                 alias overloads = __traits(getOverloads, I, "defaultArgInDerived2");
8360                 static assert(overloads.length == 2);
8361 
8362                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int))));
8363                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8364                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8365 
8366                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int))));
8367                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8368                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8369             }
8370 
8371             // @property string defaultArgInDerivedProp1(int);
8372             // @property void defaultArgInDerivedProp1(string, int);
8373             {
8374                 static assert( is(SymbolType!(I.defaultArgInDerivedProp1) ==
8375                                   ToFunctionType!(string function(int) @property)));
8376                 static assert(!__traits(compiles, PropertyType!(I.defaultArgInDerivedProp1)));
8377                 static assert(!__traits(compiles, typeof(I.defaultArgInDerivedProp1)));
8378 
8379                 alias overloads = __traits(getOverloads, I, "defaultArgInDerivedProp1");
8380                 static assert(overloads.length == 2);
8381 
8382                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int) @property)));
8383                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8384                 static assert(!__traits(compiles, typeof(overloads[0])));
8385 
8386                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int) @property)));
8387                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8388                 static assert(!__traits(compiles, typeof(overloads[0])));
8389             }
8390 
8391             // @property void defaultArgInDerivedProp2(string, int);
8392             // @property string defaultArgInDerivedProp2(int);
8393             {
8394                 static assert( is(SymbolType!(I.defaultArgInDerivedProp2) ==
8395                                   ToFunctionType!(void function(string, int) @property)));
8396                 static assert(!__traits(compiles, PropertyType!(I.defaultArgInDerivedProp2)));
8397                 static assert(!__traits(compiles, typeof(I.defaultArgInDerivedProp2)));
8398 
8399                 alias overloads = __traits(getOverloads, I, "defaultArgInDerivedProp2");
8400                 static assert(overloads.length == 2);
8401 
8402                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int) @property)));
8403                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8404                 static assert(!__traits(compiles, typeof(overloads[0])));
8405 
8406                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int) @property)));
8407                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8408                 static assert(!__traits(compiles, typeof(overloads[1])));
8409             }
8410         }
8411 
8412         // For whatever reason, the virtual functions have to have bodies, or
8413         // the linker complains, even though the functions aren't actually
8414         // called anywhere, but having them implement the functions which are in
8415         // the interface at least gets rid of the attribute inference.
8416         static class C1 : I
8417         {
8418             shared int i;
8419             string s;
8420 
8421             override void foo() {}
8422 
8423             // This shadows the one in the interface, and it has a different
8424             // signature, so it makes sure that we're getting the right one.
8425             static int bar();
8426 
8427             final void baz();
8428 
8429             override int func1() { return 0; }
8430             override void func1(int) {}
8431 
8432             override void func2(int) {}
8433             override int func2() { return 0; }
8434 
8435             override @property void prop1(int) {}
8436             override @property int prop1() { return 0; }
8437 
8438             override @property int prop2() { return 0; }
8439             override @property void prop2(int) {}
8440 
8441             override @property void extraProp(string) {}
8442             @property bool extraProp() { return true; }
8443 
8444             override int defaultArg1(string str = "foo") { return 42; }
8445             override void defaultArg1(int, string str = "foo") {}
8446 
8447             // This tests the case where the derived type doesn't provide
8448             // default arguments even though the interface does.
8449             override void defaultArg2(int, string str) {}
8450             override int defaultArg2(string str) { return 42; }
8451 
8452             override @property int defaultArgProp1(string str = "foo") { return 42; }
8453             override @property void defaultArgProp1(int, string str = "foo") {}
8454 
8455             // This tests the case where the derived type doesn't provide
8456             // default arguments even though the interface does.
8457             override @property void defaultArgProp2(int, string str) {}
8458             override @property int defaultArgProp2(string str) { return 42; }
8459 
8460             override string defaultArgInDerived1(int i = 0) { return ""; }
8461             override void defaultArgInDerived1(string, int i = 0) {}
8462 
8463             override void defaultArgInDerived2(string, int i = 0) {}
8464             override string defaultArgInDerived2(int i = 0) { return ""; }
8465 
8466             @property string defaultArgInDerivedProp1(int i = 0) { return ""; }
8467             @property void defaultArgInDerivedProp1(string, int i = 0) {}
8468 
8469             @property void defaultArgInDerivedProp2(string, int i = 0) {}
8470             @property string defaultArgInDerivedProp2(int i = 0) { return ""; }
8471         }
8472 
8473         {
8474             // shared int i;
8475             // string s;
8476             static assert( is(SymbolType!(C1.i) == shared int));
8477             static assert( is(PropertyType!(C1.i) == shared int));
8478             static assert( is(typeof(C1.i) == shared int));
8479 
8480             static assert( is(SymbolType!(C1.s) == string));
8481             static assert( is(PropertyType!(C1.s) == string));
8482             static assert( is(typeof(C1.s) == string));
8483 
8484             // override void foo()
8485             static assert( is(SymbolType!(C1.foo) == ToFunctionType!(void function())));
8486             static assert(!__traits(compiles, PropertyType!(C1.foo)));
8487             static assert( is(typeof(C1.foo) == SymbolType!(C1.foo)));
8488 
8489             // static int bar()
8490             static assert( is(SymbolType!(C1.bar) == ToFunctionType!(int function())));
8491             static assert( is(PropertyType!(C1.bar) == int));
8492             static assert( is(typeof(C1.bar) == SymbolType!(C1.bar)));
8493 
8494             // void baz()
8495             static assert( is(SymbolType!(C1.baz) == ToFunctionType!(void function())));
8496             static assert(!__traits(compiles, PropertyType!(C1.baz)));
8497             static assert( is(typeof(C1.baz) == SymbolType!(C1.baz)));
8498 
8499             // override int func1();
8500             // override void func1(int);
8501             {
8502                 static assert( is(SymbolType!(C1.func1) == ToFunctionType!(int function())));
8503                 static assert( is(PropertyType!(C1.func1) == int));
8504                 static assert( is(typeof(C1.func1) == SymbolType!(C1.func1)));
8505 
8506                 alias overloads = __traits(getOverloads, C1, "func1");
8507                 static assert(overloads.length == 2);
8508 
8509                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function())));
8510                 static assert( is(PropertyType!(overloads[0]) == int));
8511                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8512 
8513                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int))));
8514                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8515                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8516             }
8517 
8518             // override void func2(int);
8519             // override int func2();
8520             {
8521                 static assert( is(SymbolType!(C1.func2) == ToFunctionType!(void function(int))));
8522                 static assert( is(PropertyType!(C1.func2) == int));
8523                 static assert( is(typeof(C1.func2) == SymbolType!(C1.func2)));
8524 
8525                 alias overloads = __traits(getOverloads, C1, "func2");
8526                 static assert(overloads.length == 2);
8527 
8528                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int))));
8529                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8530                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8531 
8532                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function())));
8533                 static assert( is(PropertyType!(overloads[1]) == int));
8534                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8535             }
8536 
8537             // override @property void prop1(int);
8538             // override @property int prop1();
8539             {
8540                 static assert( is(SymbolType!(C1.prop1) == ToFunctionType!(void function(int) @property)));
8541                 static assert( is(PropertyType!(C1.prop1) == int));
8542                 static assert( is(typeof(C1.prop1) == PropertyType!(C1.prop1)));
8543 
8544                 alias overloads = __traits(getOverloads, C1, "prop1");
8545                 static assert(overloads.length == 2);
8546 
8547                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property)));
8548                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8549                 static assert(!__traits(compiles, typeof(overloads[0])));
8550 
8551                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property)));
8552                 static assert( is(PropertyType!(overloads[1]) == int));
8553                 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
8554             }
8555 
8556             // override @property int prop2();
8557             // override @property void prop2(int);
8558             {
8559                 static assert( is(SymbolType!(C1.prop2) == ToFunctionType!(int function() @property)));
8560                 static assert( is(PropertyType!(C1.prop2) == int));
8561                 static assert( is(typeof(C1.prop2) == PropertyType!(C1.prop2)));
8562 
8563                 alias overloads = __traits(getOverloads, C1, "prop2");
8564                 static assert(overloads.length == 2);
8565 
8566                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function() @property)));
8567                 static assert( is(PropertyType!(overloads[0]) == int));
8568                 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
8569 
8570                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int) @property)));
8571                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8572                 static assert(!__traits(compiles, typeof(overloads[1])));
8573             }
8574 
8575             // Actually on I, not C1.
8576             // static @property string staticProp();
8577             // static @property void staticProp(real);
8578             {
8579                 static assert( is(SymbolType!(C1.staticProp) == ToFunctionType!(string function() @property)));
8580                 static assert( is(PropertyType!(C1.staticProp) == string));
8581                 static assert( is(typeof(C1.staticProp) == PropertyType!(C1.staticProp)));
8582 
8583                 alias overloads = __traits(getOverloads, C1, "staticProp");
8584                 static assert(overloads.length == 2);
8585 
8586                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function() @property)));
8587                 static assert( is(PropertyType!(overloads[0]) == string));
8588                 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
8589 
8590                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(real) @property)));
8591                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8592                 static assert(!__traits(compiles, typeof(overloads[1])));
8593             }
8594 
8595             // override @property void extraProp(string);
8596             // @property bool extraProp() { return true; }
8597             {
8598                 static assert( is(SymbolType!(C1.extraProp) == ToFunctionType!(void function(string) @property)));
8599                 static assert( is(PropertyType!(C1.extraProp) == bool));
8600                 static assert( is(typeof(C1.extraProp) == bool));
8601 
8602                 alias overloads = __traits(getOverloads, C1, "extraProp");
8603                 static assert(overloads.length == 2);
8604 
8605                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string) @property)));
8606                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8607                 static assert(!__traits(compiles, typeof(overloads[0])));
8608 
8609                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(bool function() @property)));
8610                 static assert( is(PropertyType!(overloads[1]) == bool));
8611                 static assert( is(typeof(overloads[1]) == bool));
8612             }
8613 
8614             // override int defaultArg1(string str = "foo");
8615             // override void defaultArg1(int, string str = "foo");
8616             {
8617                 static assert( is(SymbolType!(C1.defaultArg1) == ToFunctionType!(int function(string))));
8618                 static assert( is(PropertyType!(C1.defaultArg1) == int));
8619                 static assert( is(typeof(C1.defaultArg1) == SymbolType!(C1.defaultArg1)));
8620 
8621                 alias overloads = __traits(getOverloads, C1, "defaultArg1");
8622                 static assert(overloads.length == 2);
8623 
8624                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string))));
8625                 static assert( is(PropertyType!(overloads[0]) == int));
8626                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8627 
8628                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string))));
8629                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8630                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8631             }
8632 
8633             // I provides default arguments, but C1 does not.
8634             // override void defaultArg2(int, string);
8635             // override int defaultArg2(string);
8636             {
8637                 static assert( is(SymbolType!(C1.defaultArg2) == ToFunctionType!(void function(int, string))));
8638                 static assert(!__traits(compiles, PropertyType!(C1.defaultArg2)));
8639                 static assert( is(typeof(C1.defaultArg2) == SymbolType!(C1.defaultArg2)));
8640 
8641                 alias overloads = __traits(getOverloads, C1, "defaultArg2");
8642                 static assert(overloads.length == 2);
8643 
8644                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string))));
8645                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8646                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8647 
8648                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string))));
8649                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8650                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8651             }
8652 
8653             // override @property int defaultArgProp1(string str = "foo");
8654             // override @property void defaultArgProp1(int, string str = "foo");
8655             {
8656                 static assert( is(SymbolType!(C1.defaultArgProp1) == ToFunctionType!(int function(string) @property)));
8657                 static assert( is(PropertyType!(C1.defaultArgProp1) == int));
8658                 static assert( is(typeof(C1.defaultArgProp1) == PropertyType!(C1.defaultArgProp1)));
8659 
8660                 alias overloads = __traits(getOverloads, C1, "defaultArgProp1");
8661                 static assert(overloads.length == 2);
8662 
8663                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string) @property)));
8664                 static assert( is(PropertyType!(overloads[0]) == int));
8665                 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
8666 
8667                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string) @property)));
8668                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8669                 static assert(!__traits(compiles, typeof(overloads[1])));
8670             }
8671 
8672             // I provides default arguments, but C1 does not.
8673             // override @property void defaultArgProp2(int, string str);
8674             // override @property int defaultArgProp2(string str);
8675             {
8676                 static assert( is(SymbolType!(C1.defaultArgProp2) ==
8677                                   ToFunctionType!(void function(int, string) @property)));
8678                 static assert(!__traits(compiles, PropertyType!(C1.defaultArgProp2)));
8679                 static assert(!__traits(compiles, typeof(C1.defaultArgProp2)));
8680 
8681                 alias overloads = __traits(getOverloads, C1, "defaultArgProp2");
8682                 static assert(overloads.length == 2);
8683 
8684                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string) @property)));
8685                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8686                 static assert(!__traits(compiles, typeof(overloads[0])));
8687 
8688                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string) @property)));
8689                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8690                 static assert(!__traits(compiles, typeof(overloads[1])));
8691             }
8692 
8693             // I does not provide default arguments, but C1 does.
8694             // override string defaultArgInDerived1(int i = 0);
8695             // override void defaultArgInDerived1(string, int i = 0);
8696             {
8697                 static assert( is(SymbolType!(C1.defaultArgInDerived1) == ToFunctionType!(string function(int))));
8698                 static assert( is(PropertyType!(C1.defaultArgInDerived1) == string));
8699                 static assert( is(typeof(C1.defaultArgInDerived1) == SymbolType!(C1.defaultArgInDerived1)));
8700 
8701                 alias overloads = __traits(getOverloads, C1, "defaultArgInDerived1");
8702                 static assert(overloads.length == 2);
8703 
8704                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int))));
8705                 static assert( is(PropertyType!(overloads[0]) == string));
8706                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8707 
8708                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int))));
8709                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8710                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8711             }
8712 
8713             // I does not provide default arguments, but C1 does.
8714             // override void defaultArgInDerived2(string, int i = 0);
8715             // override string defaultArgInDerived2(int i = 0);
8716             {
8717                 static assert( is(SymbolType!(C1.defaultArgInDerived2) == ToFunctionType!(void function(string, int))));
8718                 static assert( is(PropertyType!(C1.defaultArgInDerived2) == string));
8719                 static assert( is(typeof(C1.defaultArgInDerived2) == SymbolType!(C1.defaultArgInDerived2)));
8720 
8721                 alias overloads = __traits(getOverloads, C1, "defaultArgInDerived2");
8722                 static assert(overloads.length == 2);
8723 
8724                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int))));
8725                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8726                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8727 
8728                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int))));
8729                 static assert( is(PropertyType!(overloads[1]) == string));
8730                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8731             }
8732 
8733             // I does not provide default arguments, but C1 does.
8734             // override @property string defaultArgInDerivedProp1(int i = 0);
8735             // override @property void defaultArgInDerivedProp1(string, int i = 0);
8736             {
8737                 static assert( is(SymbolType!(C1.defaultArgInDerivedProp1) ==
8738                                   ToFunctionType!(string function(int) @property)));
8739                 static assert( is(PropertyType!(C1.defaultArgInDerivedProp1) == string));
8740                 static assert( is(typeof(C1.defaultArgInDerivedProp1) == string));
8741 
8742                 alias overloads = __traits(getOverloads, C1, "defaultArgInDerivedProp1");
8743                 static assert(overloads.length == 2);
8744 
8745                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int) @property)));
8746                 static assert( is(PropertyType!(overloads[0]) == string));
8747                 static assert( is(typeof(overloads[0]) == string));
8748 
8749                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int) @property)));
8750                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8751                 static assert(!__traits(compiles, typeof(overloads[1])));
8752             }
8753 
8754             // I does not provide default arguments, but C1 does.
8755             // override @property void defaultArgInDerivedProp2(string, int i = 0);
8756             // override @property string defaultArgInDerivedProp2(int i = 0);
8757             {
8758                 static assert( is(SymbolType!(C1.defaultArgInDerivedProp2) ==
8759                                   ToFunctionType!(void function(string, int) @property)));
8760                 static assert( is(PropertyType!(C1.defaultArgInDerivedProp2) == string));
8761                 static assert( is(typeof(C1.defaultArgInDerivedProp2) == string));
8762 
8763                 alias overloads = __traits(getOverloads, C1, "defaultArgInDerivedProp2");
8764                 static assert(overloads.length == 2);
8765 
8766                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int) @property)));
8767                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8768                 static assert(!__traits(compiles, typeof(overloads[0])));
8769 
8770                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int) @property)));
8771                 static assert( is(PropertyType!(overloads[1]) == string));
8772                 static assert( is(typeof(overloads[1]) == string));
8773             }
8774         }
8775 
8776         // Changes the function order (and has different extraProps).
8777         // It also provides default arguments when C1 does not.
8778         static class C2 : I
8779         {
8780             real r;
8781             bool b;
8782             int* ptr;
8783 
8784             @property long extraProp() { return 42; }
8785             override @property void extraProp(string) {}
8786             @property void extraProp(int) {}
8787 
8788             override void foo() {}
8789 
8790             @property string defaultArgInDerivedProp2(int i = 0) { return "dlang"; }
8791             @property void defaultArgInDerivedProp2(string, int i = 0) {}
8792 
8793             string defaultArgInDerived2(int i = 0) { return "dlang"; }
8794             void defaultArgInDerived2(string, int i = 0) {}
8795 
8796             void defaultArgInDerived1(string, int i = 0) {}
8797             string defaultArgInDerived1(int i = 0) { return "dlang"; }
8798 
8799             @property void defaultArgInDerivedProp1(string, int i = 0) {}
8800             @property string defaultArgInDerivedProp1(int i = 0) { return "dlang"; }
8801 
8802             override void defaultArg2(int, string str = "bar") {}
8803             override int defaultArg2(string str = "bar") { return 0; }
8804 
8805             override @property int defaultArgProp2(string str = "bar") { return 0; }
8806             override @property void defaultArgProp2(int, string str = "bar") {}
8807 
8808             override @property void defaultArgProp1(int, string str = "bar") {}
8809             override @property int defaultArgProp1(string str = "bar") { return 0; }
8810 
8811             override void defaultArg1(int, string str = "bar") {}
8812             override int defaultArg1(string str = "bar") { return 0; }
8813 
8814             override @property void prop2(int) {}
8815             override @property int prop2() { return 0; }
8816 
8817             override @property void prop1(int) {}
8818             override @property int prop1() { return 0; }
8819 
8820             override void func2(int) {}
8821             override int func2() { return 0; }
8822 
8823             override int func1() { return 0; }
8824             override void func1(int) {}
8825         }
8826 
8827         {
8828             // real r;
8829             // bool b;
8830             // int* ptr;
8831 
8832             static assert( is(SymbolType!(C2.r) == real));
8833             static assert( is(PropertyType!(C2.r) == real));
8834             static assert( is(typeof(C2.r) == real));
8835 
8836             static assert( is(SymbolType!(C2.b) == bool));
8837             static assert( is(PropertyType!(C2.b) == bool));
8838             static assert( is(typeof(C2.b) == bool));
8839 
8840             static assert( is(SymbolType!(C2.ptr) == int*));
8841             static assert( is(PropertyType!(C2.ptr) == int*));
8842             static assert( is(typeof(C2.ptr) == int*));
8843 
8844             // Actually on I, not C2.
8845             // static @property string staticProp();
8846             // static @property void staticProp(real);
8847             {
8848                 static assert( is(SymbolType!(C2.staticProp) == ToFunctionType!(string function() @property)));
8849                 static assert( is(PropertyType!(C2.staticProp) == string));
8850                 static assert( is(typeof(C2.staticProp) == PropertyType!(C2.staticProp)));
8851 
8852                 alias overloads = __traits(getOverloads, C2, "staticProp");
8853                 static assert(overloads.length == 2);
8854 
8855                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function() @property)));
8856                 static assert( is(PropertyType!(overloads[0]) == string));
8857                 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
8858 
8859                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(real) @property)));
8860                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8861                 static assert(!__traits(compiles, typeof(overloads[1])));
8862             }
8863 
8864             // @property long extraProp() { return 42; }
8865             // override @property void extraProp(string) {}
8866             // @property void extraProp(int) {}
8867             {
8868                 static assert( is(SymbolType!(C2.extraProp) == ToFunctionType!(long function() @property)));
8869                 static assert( is(PropertyType!(C2.extraProp) == long));
8870                 static assert( is(typeof(C2.extraProp) == long));
8871 
8872                 alias overloads = __traits(getOverloads, C2, "extraProp");
8873                 static assert(overloads.length == 3);
8874 
8875                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function() @property)));
8876                 static assert( is(PropertyType!(overloads[0]) == long));
8877                 static assert( is(typeof(overloads[0]) == long));
8878 
8879                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string) @property)));
8880                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8881                 static assert(!__traits(compiles, typeof(overloads[1])));
8882 
8883                 static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(void function(int) @property)));
8884                 static assert(!__traits(compiles, PropertyType!(overloads[2])));
8885                 static assert(!__traits(compiles, typeof(overloads[2])));
8886             }
8887 
8888             // override void foo()
8889             static assert( is(SymbolType!(C2.foo) == ToFunctionType!(void function())));
8890             static assert(!__traits(compiles, PropertyType!(C2.foo)));
8891             static assert( is(typeof(C2.foo) == SymbolType!(C2.foo)));
8892 
8893             // I does not provide default arguments, but C2 does.
8894             // @property string defaultArgInDerivedProp2(int i = 0);
8895             // @property void defaultArgInDerivedProp2(string, int i = 0);
8896             {
8897                 static assert( is(SymbolType!(C2.defaultArgInDerivedProp2) ==
8898                                   ToFunctionType!(string function(int) @property)));
8899                 static assert( is(PropertyType!(C2.defaultArgInDerivedProp2) == string));
8900                 static assert( is(typeof(C2.defaultArgInDerivedProp2) == string));
8901 
8902                 alias overloads = __traits(getOverloads, C2, "defaultArgInDerivedProp2");
8903                 static assert(overloads.length == 2);
8904 
8905                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int) @property)));
8906                 static assert( is(PropertyType!(overloads[0]) == string));
8907                 static assert( is(typeof(overloads[0]) == string));
8908 
8909                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int) @property)));
8910                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8911                 static assert(!__traits(compiles, typeof(overloads[1])));
8912             }
8913 
8914             // I does not provide default arguments, but C2 does.
8915             // string defaultArgInDerived2(int i = 0);
8916             // void defaultArgInDerived2(string, int i = 0);
8917             {
8918                 static assert( is(SymbolType!(C2.defaultArgInDerived2) == ToFunctionType!(string function(int))));
8919                 static assert( is(PropertyType!(C2.defaultArgInDerived2) == string));
8920                 static assert( is(typeof(C2.defaultArgInDerived2) == SymbolType!(C2.defaultArgInDerived2)));
8921 
8922                 alias overloads = __traits(getOverloads, C2, "defaultArgInDerived2");
8923                 static assert(overloads.length == 2);
8924 
8925                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int))));
8926                 static assert( is(PropertyType!(overloads[0]) == string));
8927                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8928 
8929                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int))));
8930                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8931                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8932             }
8933 
8934             // I does not provide default arguments, but C2 does.
8935             // void defaultArgInDerived1(string, int i = 0);
8936             // string defaultArgInDerived1(int i = 0);
8937             {
8938                 static assert( is(SymbolType!(C2.defaultArgInDerived1) == ToFunctionType!(void function(string, int))));
8939                 static assert( is(PropertyType!(C2.defaultArgInDerived1) == string));
8940                 static assert( is(typeof(C2.defaultArgInDerived1) == SymbolType!(C2.defaultArgInDerived1)));
8941 
8942                 alias overloads = __traits(getOverloads, C2, "defaultArgInDerived1");
8943                 static assert(overloads.length == 2);
8944 
8945                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int))));
8946                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8947                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8948 
8949                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int))));
8950                 static assert( is(PropertyType!(overloads[1]) == string));
8951                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8952             }
8953 
8954             // I does not provide default arguments, but C2 does.
8955             // @property void defaultArgInDerivedProp1(string, int i = 0);
8956             // @property string defaultArgInDerivedProp1(int i = 0);
8957             {
8958                 static assert( is(SymbolType!(C2.defaultArgInDerivedProp1) ==
8959                                   ToFunctionType!(void function(string, int) @property)));
8960                 static assert( is(PropertyType!(C2.defaultArgInDerivedProp1) == string));
8961                 static assert( is(typeof(C2.defaultArgInDerivedProp1) == string));
8962 
8963                 alias overloads = __traits(getOverloads, C2, "defaultArgInDerivedProp1");
8964                 static assert(overloads.length == 2);
8965 
8966                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int) @property)));
8967                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8968                 static assert(!__traits(compiles, typeof(overloads[0])));
8969 
8970                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int) @property)));
8971                 static assert( is(PropertyType!(overloads[1]) == string));
8972                 static assert( is(typeof(overloads[1]) == string));
8973             }
8974 
8975             // override void defaultArg2(int, string str = "bar");
8976             // override int defaultArg2(string str = "bar");
8977             {
8978                 static assert( is(SymbolType!(C2.defaultArg2) == ToFunctionType!(void function(int, string))));
8979                 static assert( is(PropertyType!(C2.defaultArg2) == int));
8980                 static assert( is(typeof(C2.defaultArg2) == SymbolType!(C2.defaultArg2)));
8981 
8982                 alias overloads = __traits(getOverloads, C2, "defaultArg2");
8983                 static assert(overloads.length == 2);
8984 
8985                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string))));
8986                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8987                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8988 
8989                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string))));
8990                 static assert( is(PropertyType!(overloads[1]) == int));
8991                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8992             }
8993 
8994             // override @property int defaultArgProp2(string str = "bar");
8995             // override @property void defaultArgProp2(int, string str = "bar");
8996             {
8997                 static assert( is(SymbolType!(C2.defaultArgProp2) ==
8998                                   ToFunctionType!(int function(string) @property)));
8999                 static assert( is(PropertyType!(C2.defaultArgProp2) == int));
9000                 static assert( is(typeof(C2.defaultArgProp2) == PropertyType!(C2.defaultArgProp2)));
9001 
9002                 alias overloads = __traits(getOverloads, C2, "defaultArgProp2");
9003                 static assert(overloads.length == 2);
9004 
9005                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string) @property)));
9006                 static assert( is(PropertyType!(overloads[0]) == int));
9007                 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
9008 
9009                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string) @property)));
9010                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
9011                 static assert(!__traits(compiles, typeof(overloads[1])));
9012             }
9013 
9014             // override @property void defaultArgProp1(int, string str = "bar");
9015             // override @property int defaultArgProp1(string str = "bar");
9016             {
9017 
9018                 static assert( is(SymbolType!(C2.defaultArgProp1) ==
9019                                   ToFunctionType!(void function(int, string) @property)));
9020                 static assert( is(PropertyType!(C2.defaultArgProp1) == int));
9021                 static assert( is(typeof(C2.defaultArgProp1) == PropertyType!(C2.defaultArgProp1)));
9022 
9023                 alias overloads = __traits(getOverloads, C2, "defaultArgProp1");
9024                 static assert(overloads.length == 2);
9025 
9026                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string) @property)));
9027                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9028                 static assert(!__traits(compiles, typeof(overloads[0])));
9029 
9030                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string) @property)));
9031                 static assert( is(PropertyType!(overloads[1]) == int));
9032                 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
9033             }
9034 
9035             // override void defaultArg1(int, string str = "bar");
9036             // override int defaultArg1(string str = "bar");
9037             {
9038                 static assert( is(SymbolType!(C2.defaultArg1) == ToFunctionType!(void function(int, string))));
9039                 static assert( is(PropertyType!(C2.defaultArg1) == int));
9040                 static assert( is(typeof(C2.defaultArg1) == SymbolType!(C2.defaultArg1)));
9041 
9042                 alias overloads = __traits(getOverloads, C2, "defaultArg1");
9043                 static assert(overloads.length == 2);
9044 
9045                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string))));
9046                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9047                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
9048 
9049                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string))));
9050                 static assert( is(PropertyType!(overloads[1]) == int));
9051                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
9052             }
9053 
9054             // override @property void prop2(int);
9055             // override @property int prop2();
9056             {
9057                 static assert( is(SymbolType!(C2.prop2) == ToFunctionType!(void function(int) @property)));
9058                 static assert( is(PropertyType!(C2.prop2) == int));
9059                 static assert( is(typeof(C2.prop2) == PropertyType!(C2.prop2)));
9060 
9061                 alias overloads = __traits(getOverloads, C2, "prop2");
9062                 static assert(overloads.length == 2);
9063 
9064                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property)));
9065                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9066                 static assert(!__traits(compiles, typeof(overloads[0])));
9067 
9068                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property)));
9069                 static assert( is(PropertyType!(overloads[1]) == int));
9070                 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
9071             }
9072 
9073             // override @property void prop1(int);
9074             // override @property int prop1();
9075             {
9076                 static assert( is(SymbolType!(C2.prop1) == ToFunctionType!(void function(int) @property)));
9077                 static assert( is(PropertyType!(C2.prop1) == int));
9078                 static assert( is(typeof(C2.prop1) == PropertyType!(C2.prop1)));
9079 
9080                 alias overloads = __traits(getOverloads, C2, "prop1");
9081                 static assert(overloads.length == 2);
9082 
9083                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property)));
9084                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9085                 static assert(!__traits(compiles, typeof(overloads[0])));
9086 
9087                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property)));
9088                 static assert( is(PropertyType!(overloads[1]) == int));
9089                 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
9090             }
9091 
9092             // override void func2(int);
9093             // override int func2();
9094             {
9095                 static assert( is(SymbolType!(C2.func2) == ToFunctionType!(void function(int))));
9096                 static assert( is(PropertyType!(C2.func2) == int));
9097                 static assert( is(typeof(C2.func2) == SymbolType!(C2.func2)));
9098 
9099                 alias overloads = __traits(getOverloads, C2, "func2");
9100                 static assert(overloads.length == 2);
9101 
9102                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int))));
9103                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9104                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
9105 
9106                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function())));
9107                 static assert( is(PropertyType!(overloads[1]) == int));
9108                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
9109             }
9110 
9111             // override int func1();
9112             // override void func1(int);
9113             {
9114                 static assert( is(SymbolType!(C2.func1) == ToFunctionType!(int function())));
9115                 static assert( is(PropertyType!(C2.func1) == int));
9116                 static assert( is(typeof(C2.func1) == SymbolType!(C2.func1)));
9117 
9118                 alias overloads = __traits(getOverloads, C2, "func1");
9119                 static assert(overloads.length == 2);
9120 
9121                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function())));
9122                 static assert( is(PropertyType!(overloads[0]) == int));
9123                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
9124 
9125                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int))));
9126                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
9127                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
9128             }
9129         }
9130 
9131         static class C3 : C2
9132         {
9133             const(short)* ptr;
9134         }
9135 
9136         {
9137             // real r; (from C2)
9138             // bool b; (from C2)
9139             // const(short)* ptr; (shadows C2.ptr)
9140             static assert( is(SymbolType!(C3.r) == real));
9141             static assert( is(PropertyType!(C3.r) == real));
9142             static assert( is(typeof(C3.r) == real));
9143 
9144             static assert( is(SymbolType!(C3.b) == bool));
9145             static assert( is(PropertyType!(C3.b) == bool));
9146             static assert( is(typeof(C3.b) == bool));
9147 
9148             static assert( is(SymbolType!(C3.ptr) == const(short)*));
9149             static assert( is(PropertyType!(C3.ptr) == const(short)*));
9150             static assert( is(typeof(C3.ptr) == const(short)*));
9151 
9152             // Actually on I, not C3.
9153             // static @property string staticProp();
9154             // static @property void staticProp(real);
9155             {
9156                 static assert( is(SymbolType!(C3.staticProp) == ToFunctionType!(string function() @property)));
9157                 static assert( is(PropertyType!(C3.staticProp) == string));
9158                 static assert( is(typeof(C3.staticProp) == PropertyType!(C3.staticProp)));
9159 
9160                 alias overloads = __traits(getOverloads, C3, "staticProp");
9161                 static assert(overloads.length == 2);
9162 
9163                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function() @property)));
9164                 static assert( is(PropertyType!(overloads[0]) == string));
9165                 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
9166 
9167                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(real) @property)));
9168                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
9169                 static assert(!__traits(compiles, typeof(overloads[1])));
9170             }
9171 
9172             // @property long extraProp() { return 42; }
9173             // override @property void extraProp(string) {}
9174             // @property void extraProp(int) {}
9175             {
9176                 static assert( is(SymbolType!(C3.extraProp) == ToFunctionType!(long function() @property)));
9177                 static assert( is(PropertyType!(C3.extraProp) == long));
9178                 static assert( is(typeof(C3.extraProp) == long));
9179 
9180                 alias overloads = __traits(getOverloads, C3, "extraProp");
9181                 static assert(overloads.length == 3);
9182 
9183                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function() @property)));
9184                 static assert( is(PropertyType!(overloads[0]) == long));
9185                 static assert( is(typeof(overloads[0]) == long));
9186 
9187                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string) @property)));
9188                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
9189                 static assert(!__traits(compiles, typeof(overloads[1])));
9190 
9191                 static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(void function(int) @property)));
9192                 static assert(!__traits(compiles, PropertyType!(overloads[2])));
9193                 static assert(!__traits(compiles, typeof(overloads[2])));
9194             }
9195 
9196             // override void foo()
9197             static assert( is(SymbolType!(C3.foo) == ToFunctionType!(void function())));
9198             static assert(!__traits(compiles, PropertyType!(C3.foo)));
9199             static assert( is(typeof(C3.foo) == SymbolType!(C3.foo)));
9200 
9201             // I does not provide default arguments, but C2 does.
9202             // @property string defaultArgInDerivedProp2(int i = 0);
9203             // @property void defaultArgInDerivedProp2(string, int i = 0);
9204             {
9205                 static assert( is(SymbolType!(C3.defaultArgInDerivedProp2) ==
9206                                   ToFunctionType!(string function(int) @property)));
9207                 static assert( is(PropertyType!(C3.defaultArgInDerivedProp2) == string));
9208                 static assert( is(typeof(C3.defaultArgInDerivedProp2) == string));
9209 
9210                 alias overloads = __traits(getOverloads, C3, "defaultArgInDerivedProp2");
9211                 static assert(overloads.length == 2);
9212 
9213                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int) @property)));
9214                 static assert( is(PropertyType!(overloads[0]) == string));
9215                 static assert( is(typeof(overloads[0]) == string));
9216 
9217                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int) @property)));
9218                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
9219                 static assert(!__traits(compiles, typeof(overloads[1])));
9220             }
9221 
9222             // I does not provide default arguments, but C2 does.
9223             // string defaultArgInDerived2(int i = 0);
9224             // void defaultArgInDerived2(string, int i = 0);
9225             {
9226                 static assert( is(SymbolType!(C3.defaultArgInDerived2) == ToFunctionType!(string function(int))));
9227                 static assert( is(PropertyType!(C3.defaultArgInDerived2) == string));
9228                 static assert( is(typeof(C3.defaultArgInDerived2) == SymbolType!(C3.defaultArgInDerived2)));
9229 
9230                 alias overloads = __traits(getOverloads, C3, "defaultArgInDerived2");
9231                 static assert(overloads.length == 2);
9232 
9233                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int))));
9234                 static assert( is(PropertyType!(overloads[0]) == string));
9235                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
9236 
9237                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int))));
9238                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
9239                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
9240             }
9241 
9242             // I does not provide default arguments, but C2 does.
9243             // void defaultArgInDerived1(string, int i = 0);
9244             // string defaultArgInDerived1(int i = 0);
9245             {
9246                 static assert( is(SymbolType!(C3.defaultArgInDerived1) == ToFunctionType!(void function(string, int))));
9247                 static assert( is(PropertyType!(C3.defaultArgInDerived1) == string));
9248                 static assert( is(typeof(C3.defaultArgInDerived1) == SymbolType!(C3.defaultArgInDerived1)));
9249 
9250                 alias overloads = __traits(getOverloads, C3, "defaultArgInDerived1");
9251                 static assert(overloads.length == 2);
9252 
9253                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int))));
9254                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9255                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
9256 
9257                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int))));
9258                 static assert( is(PropertyType!(overloads[1]) == string));
9259                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
9260             }
9261 
9262             // I does not provide default arguments, but C2 does.
9263             // @property void defaultArgInDerivedProp1(string, int i = 0);
9264             // @property string defaultArgInDerivedProp1(int i = 0);
9265             {
9266                 static assert( is(SymbolType!(C3.defaultArgInDerivedProp1) ==
9267                                   ToFunctionType!(void function(string, int) @property)));
9268                 static assert( is(PropertyType!(C3.defaultArgInDerivedProp1) == string));
9269                 static assert( is(typeof(C3.defaultArgInDerivedProp1) == string));
9270 
9271                 alias overloads = __traits(getOverloads, C3, "defaultArgInDerivedProp1");
9272                 static assert(overloads.length == 2);
9273 
9274                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int) @property)));
9275                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9276                 static assert(!__traits(compiles, typeof(overloads[0])));
9277 
9278                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int) @property)));
9279                 static assert( is(PropertyType!(overloads[1]) == string));
9280                 static assert( is(typeof(overloads[1]) == string));
9281             }
9282 
9283             // override void defaultArg2(int, string str = "bar");
9284             // override int defaultArg2(string str = "bar");
9285             {
9286                 static assert( is(SymbolType!(C3.defaultArg2) == ToFunctionType!(void function(int, string))));
9287                 static assert( is(PropertyType!(C3.defaultArg2) == int));
9288                 static assert( is(typeof(C3.defaultArg2) == SymbolType!(C3.defaultArg2)));
9289 
9290                 alias overloads = __traits(getOverloads, C3, "defaultArg2");
9291                 static assert(overloads.length == 2);
9292 
9293                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string))));
9294                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9295                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
9296 
9297                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string))));
9298                 static assert( is(PropertyType!(overloads[1]) == int));
9299                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
9300             }
9301 
9302             // override @property int defaultArgProp2(string str = "bar");
9303             // override @property void defaultArgProp2(int, string str = "bar");
9304             {
9305                 static assert( is(SymbolType!(C3.defaultArgProp2) ==
9306                                   ToFunctionType!(int function(string) @property)));
9307                 static assert( is(PropertyType!(C3.defaultArgProp2) == int));
9308                 static assert( is(typeof(C3.defaultArgProp2) == PropertyType!(C3.defaultArgProp2)));
9309 
9310                 alias overloads = __traits(getOverloads, C3, "defaultArgProp2");
9311                 static assert(overloads.length == 2);
9312 
9313                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string) @property)));
9314                 static assert( is(PropertyType!(overloads[0]) == int));
9315                 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
9316 
9317                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string) @property)));
9318                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
9319                 static assert(!__traits(compiles, typeof(overloads[1])));
9320             }
9321 
9322             // override @property void defaultArgProp1(int, string str = "bar");
9323             // override @property int defaultArgProp1(string str = "bar");
9324             {
9325 
9326                 static assert( is(SymbolType!(C3.defaultArgProp1) ==
9327                                   ToFunctionType!(void function(int, string) @property)));
9328                 static assert( is(PropertyType!(C3.defaultArgProp1) == int));
9329                 static assert( is(typeof(C3.defaultArgProp1) == PropertyType!(C3.defaultArgProp1)));
9330 
9331                 alias overloads = __traits(getOverloads, C3, "defaultArgProp1");
9332                 static assert(overloads.length == 2);
9333 
9334                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string) @property)));
9335                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9336                 static assert(!__traits(compiles, typeof(overloads[0])));
9337 
9338                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string) @property)));
9339                 static assert( is(PropertyType!(overloads[1]) == int));
9340                 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
9341             }
9342 
9343             // override void defaultArg1(int, string str = "bar");
9344             // override int defaultArg1(string str = "bar");
9345             {
9346                 static assert( is(SymbolType!(C3.defaultArg1) == ToFunctionType!(void function(int, string))));
9347                 static assert( is(PropertyType!(C3.defaultArg1) == int));
9348                 static assert( is(typeof(C3.defaultArg1) == SymbolType!(C3.defaultArg1)));
9349 
9350                 alias overloads = __traits(getOverloads, C3, "defaultArg1");
9351                 static assert(overloads.length == 2);
9352 
9353                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string))));
9354                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9355                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
9356 
9357                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string))));
9358                 static assert( is(PropertyType!(overloads[1]) == int));
9359                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
9360             }
9361 
9362             // override @property void prop2(int);
9363             // override @property int prop2();
9364             {
9365                 static assert( is(SymbolType!(C3.prop2) == ToFunctionType!(void function(int) @property)));
9366                 static assert( is(PropertyType!(C3.prop2) == int));
9367                 static assert( is(typeof(C3.prop2) == PropertyType!(C3.prop2)));
9368 
9369                 alias overloads = __traits(getOverloads, C3, "prop2");
9370                 static assert(overloads.length == 2);
9371 
9372                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property)));
9373                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9374                 static assert(!__traits(compiles, typeof(overloads[0])));
9375 
9376                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property)));
9377                 static assert( is(PropertyType!(overloads[1]) == int));
9378                 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
9379             }
9380 
9381             // override @property void prop1(int);
9382             // override @property int prop1();
9383             {
9384                 static assert( is(SymbolType!(C3.prop1) == ToFunctionType!(void function(int) @property)));
9385                 static assert( is(PropertyType!(C3.prop1) == int));
9386                 static assert( is(typeof(C3.prop1) == PropertyType!(C3.prop1)));
9387 
9388                 alias overloads = __traits(getOverloads, C3, "prop1");
9389                 static assert(overloads.length == 2);
9390 
9391                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property)));
9392                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9393                 static assert(!__traits(compiles, typeof(overloads[0])));
9394 
9395                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property)));
9396                 static assert( is(PropertyType!(overloads[1]) == int));
9397                 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
9398             }
9399 
9400             // override void func2(int);
9401             // override int func2();
9402             {
9403                 static assert( is(SymbolType!(C3.func2) == ToFunctionType!(void function(int))));
9404                 static assert( is(PropertyType!(C3.func2) == int));
9405                 static assert( is(typeof(C3.func2) == SymbolType!(C3.func2)));
9406 
9407                 alias overloads = __traits(getOverloads, C3, "func2");
9408                 static assert(overloads.length == 2);
9409 
9410                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int))));
9411                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9412                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
9413 
9414                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function())));
9415                 static assert( is(PropertyType!(overloads[1]) == int));
9416                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
9417             }
9418 
9419             // override int func1();
9420             // override void func1(int);
9421             {
9422                 static assert( is(SymbolType!(C3.func1) == ToFunctionType!(int function())));
9423                 static assert( is(PropertyType!(C3.func1) == int));
9424                 static assert( is(typeof(C3.func1) == SymbolType!(C3.func1)));
9425 
9426                 alias overloads = __traits(getOverloads, C3, "func1");
9427                 static assert(overloads.length == 2);
9428 
9429                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function())));
9430                 static assert( is(PropertyType!(overloads[0]) == int));
9431                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
9432 
9433                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int))));
9434                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
9435                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
9436             }
9437         }
9438     }
9439 }
9440 
9441 // This is probably overkill, since it's arguably testing the compiler more
9442 // than it's testing SymbolType or ToFunctionType, but with various tests
9443 // either using inference for all attributes or not providing a body to avoid
9444 // it entirely, it seemed prudent to add some tests where the attributes being
9445 // inferred were better controlled, and it does help ensure that SymbolType
9446 // and ToFunctionType behave as expected in each case.
9447 @safe unittest
9448 {
9449     static int var;
9450 
9451     // Since these are actually called below (even if those functions aren't
9452     // called) we can't play the trick of not providing a body to set all of
9453     // the attributes, because we get linker errors when the functions below
9454     // call these functions.
9455     static void useGC() @safe pure nothrow { new int; }
9456     static void throws() @safe pure @nogc { Exception e; throw e; }
9457     static void impure() @safe nothrow @nogc { ++var; }
9458     static void unsafe() @system pure nothrow @nogc { int i; int* ptr = &i; }
9459 
9460     {
9461         static void func() { useGC(); }
9462         static assert( is(typeof(func) == ToFunctionType!(void function() @safe pure nothrow)));
9463         static assert( is(SymbolType!func == ToFunctionType!(void function() @safe pure nothrow)));
9464     }
9465     {
9466         static void func() { throws(); }
9467         static assert( is(typeof(func) == ToFunctionType!(void function() @safe pure @nogc)));
9468         static assert( is(SymbolType!func == ToFunctionType!(void function() @safe pure @nogc)));
9469     }
9470     {
9471         static void func() { impure(); }
9472         static assert( is(typeof(func) == ToFunctionType!(void function() @safe nothrow @nogc)));
9473         static assert( is(SymbolType!func == ToFunctionType!(void function() @safe nothrow @nogc)));
9474     }
9475     {
9476         static void func() { unsafe(); }
9477         static assert( is(typeof(func) == ToFunctionType!(void function() @system pure nothrow @nogc)));
9478 
9479         // Doubling the test shouldn't be necessary, but since the order of the
9480         // attributes isn't supposed to matter, it seemed prudent to have at
9481         // least one test that used a different order.
9482         static assert( is(SymbolType!func == ToFunctionType!(void function() @system pure nothrow @nogc)));
9483         static assert( is(SymbolType!func == ToFunctionType!(void function() @nogc nothrow pure @system)));
9484     }
9485     {
9486         static void func() { useGC(); throws(); }
9487         static assert( is(typeof(func) == ToFunctionType!(void function() @safe pure)));
9488         static assert( is(SymbolType!func == ToFunctionType!(void function() @safe pure)));
9489     }
9490     {
9491         static void func() { throws(); impure(); }
9492         static assert( is(typeof(func) == ToFunctionType!(void function() @safe @nogc)));
9493         static assert( is(SymbolType!func == ToFunctionType!(void function() @safe @nogc)));
9494     }
9495     {
9496         static void func() { impure(); unsafe(); }
9497         static assert( is(typeof(func) == ToFunctionType!(void function() @system nothrow @nogc)));
9498         static assert( is(SymbolType!func == ToFunctionType!(void function() @system nothrow @nogc)));
9499     }
9500     {
9501         static void func() { useGC(); unsafe(); }
9502         static assert( is(typeof(func) == ToFunctionType!(void function() @system pure nothrow)));
9503         static assert( is(SymbolType!func == ToFunctionType!(void function() @system pure nothrow)));
9504     }
9505     {
9506         static void func() { useGC(); throws(); impure(); unsafe(); }
9507         static assert( is(typeof(func) == ToFunctionType!(void function() @system)));
9508         static assert( is(SymbolType!func == ToFunctionType!(void function() @system)));
9509     }
9510     {
9511         static void func() @trusted { useGC(); throws(); impure(); unsafe(); }
9512         static assert( is(typeof(func) == ToFunctionType!(void function() @trusted)));
9513         static assert( is(SymbolType!func == ToFunctionType!(void function() @trusted)));
9514     }
9515 }
9516 
9517 /++
9518     Removes the outer layer of $(D const), $(D inout), or $(D immutable)
9519     from type $(D T).
9520 
9521     If none of those qualifiers have been applied to the outer layer of
9522     type $(D T), then the result is $(D T).
9523 
9524     For the built-in scalar types (that is $(D bool), the character types, and
9525     the numeric types), they only have one layer, so $(D const U) simply becomes
9526     $(D U).
9527 
9528     Where the layers come in is pointers and arrays. $(D const(U*)) becomes
9529     $(D const(U)*), and $(D const(U[])), becomes $(D const(U)[]). So, a pointer
9530     goes from being fully $(D const) to being a mutable pointer to $(D const),
9531     and a dynamic array goes from being fully $(D const) to being a mutable
9532     dynamic array of $(D const) elements. And if there are multiple layers of
9533     pointers or arrays, it's just that outer layer which is affected - e.g.
9534     $(D const(U**)) would become $(D const(U*)*).
9535 
9536     For user-defined types, the effect is that $(D const U) becomes $(D U), and
9537     how that affects member variables depends on the type of the member
9538     variable. If a member variable is explicitly marked with any mutability
9539     qualifiers, then it will continue to have those qualifiers even after
9540     Unconst has stripped all mutability qualifiers from the containing type.
9541     However, if a mutability qualifier was on the member variable only because
9542     the containing type had that qualifier, then when Unconst removes the
9543     qualifier from the containing type, it is removed from the member variable
9544     as well.
9545 
9546     Also, Unconst has no effect on what a templated type is instantiated
9547     with, so if a templated type is instantiated with a template argument which
9548     has a mutability qualifier, the template instantiation will not change.
9549   +/
9550 version (StdDdoc) template Unconst(T)
9551 {
9552     import core.internal.traits : CoreUnconst = Unconst;
9553     alias Unconst = CoreUnconst!T;
9554 }
9555 else
9556 {
9557     import core.internal.traits : CoreUnconst = Unconst;
9558     alias Unconst = CoreUnconst;
9559 }
9560 
9561 ///
9562 @safe unittest
9563 {
9564     static assert(is(Unconst!(                   int) == int));
9565     static assert(is(Unconst!(             const int) == int));
9566     static assert(is(Unconst!(       inout       int) == int));
9567     static assert(is(Unconst!(       inout const int) == int));
9568     static assert(is(Unconst!(shared             int) == shared int));
9569     static assert(is(Unconst!(shared       const int) == shared int));
9570     static assert(is(Unconst!(shared inout       int) == shared int));
9571     static assert(is(Unconst!(shared inout const int) == shared int));
9572     static assert(is(Unconst!(         immutable int) == int));
9573 
9574     // Only the outer layer of immutable is removed.
9575     // immutable(int[]) -> immutable(int)[]
9576     alias ImmIntArr = immutable(int[]);
9577     static assert(is(Unconst!ImmIntArr == immutable(int)[]));
9578 
9579     // Only the outer layer of const is removed.
9580     // immutable(int*) -> immutable(int)*
9581     alias ConstIntPtr = const(int*);
9582     static assert(is(Unconst!ConstIntPtr == const(int)*));
9583 
9584     // const(int)* -> const(int)*
9585     alias PtrToConstInt = const(int)*;
9586     static assert(is(Unconst!PtrToConstInt == const(int)*));
9587 
9588     static struct S
9589     {
9590         int* ptr;
9591         const int* cPtr;
9592         shared int* sPtr;
9593     }
9594 
9595     const S s;
9596     static assert(is(typeof(s) == const S));
9597     static assert(is(typeof(typeof(s).ptr) == const int*));
9598     static assert(is(typeof(typeof(s).cPtr) == const int*));
9599     static assert(is(typeof(typeof(s).sPtr) == const shared int*));
9600 
9601     // For user-defined types, all mutability qualifiers that are applied to
9602     // member variables only because the containing type has them are removed,
9603     // but the ones that are directly on those member variables remain.
9604 
9605     // const S -> S
9606     static assert(is(Unconst!(typeof(s)) == S));
9607     static assert(is(typeof(Unconst!(typeof(s)).ptr) == int*));
9608     static assert(is(typeof(Unconst!(typeof(s)).cPtr) == const int*));
9609     static assert(is(typeof(Unconst!(typeof(s)).sPtr) == shared int*));
9610 
9611     static struct Foo(T)
9612     {
9613         T* ptr;
9614     }
9615 
9616     // The qualifier on the type is removed, but the qualifier on the template
9617     // argument is not.
9618     static assert(is(Unconst!(const(Foo!(const int))) == Foo!(const int)));
9619     static assert(is(Unconst!(Foo!(const int)) == Foo!(const int)));
9620     static assert(is(Unconst!(const(Foo!int)) == Foo!int));
9621 }
9622 
9623 /++
9624     Removes the outer layer of $(D shared) from type $(D T).
9625 
9626     If $(D shared) has not been applied to the outer layer of type $(D T), then
9627     the result is $(D T).
9628 
9629     Note that while $(D immutable) is implicitly $(D shared), it is unaffected
9630     by Unshared. Only explicit $(D shared) is removed.
9631 
9632     For the built-in scalar types (that is $(D bool), the character types, and
9633     the numeric types), they only have one layer, so $(D shared U) simply
9634     becomes $(D U).
9635 
9636     Where the layers come in is pointers and arrays. $(D shared(U*)) becomes
9637     $(D shared(U)*), and $(D shared(U[])), becomes $(D shared(U)[]). So, a
9638     pointer goes from being fully $(D shared) to being a mutable pointer to
9639     $(D shared), and a dynamic array goes from being fully $(D shared) to being
9640     a mutable dynamic array of $(D shared) elements. And if there are multiple
9641     layers of pointers or arrays, it's just that outer layer which is affected
9642     - e.g. $(D shared(U**)) would become $(D shared(U*)*).
9643 
9644     For user-defined types, the effect is that $(D shared U) becomes $(D U),
9645     and how that affects member variables depends on the type of the member
9646     variable. If a member variable is explicitly marked with $(D shared), then
9647     it will continue to be $(D shared) even after Unshared has stripped
9648     $(D shared) from the containing type. However, if $(D shared) was on the
9649     member variable only because the containing type was $(D shared), then when
9650     Unshared removes the qualifier from the containing type, it is removed from
9651     the member variable as well.
9652 
9653     Also, Unshared has no effect on what a templated type is instantiated
9654     with, so if a templated type is instantiated with a template argument which
9655     has a type qualifier, the template instantiation will not change.
9656   +/
9657 template Unshared(T)
9658 {
9659     static if (is(T == shared U, U))
9660         alias Unshared = U;
9661     else
9662         alias Unshared = T;
9663 }
9664 
9665 ///
9666 @safe unittest
9667 {
9668     static assert(is(Unshared!(                   int) == int));
9669     static assert(is(Unshared!(             const int) == const int));
9670     static assert(is(Unshared!(       inout       int) == inout int));
9671     static assert(is(Unshared!(       inout const int) == inout const int));
9672     static assert(is(Unshared!(shared             int) == int));
9673     static assert(is(Unshared!(shared       const int) == const int));
9674     static assert(is(Unshared!(shared inout       int) == inout int));
9675     static assert(is(Unshared!(shared inout const int) == inout const int));
9676     static assert(is(Unshared!(         immutable int) == immutable int));
9677 
9678     // Only the outer layer of shared is removed.
9679     // shared(int[]) -> shared(int)[]
9680     alias SharedIntArr = shared(int[]);
9681     static assert(is(Unshared!SharedIntArr == shared(int)[]));
9682 
9683     // Only the outer layer of shared is removed.
9684     // shared(int*) -> shared(int)*
9685     alias SharedIntPtr = shared(int*);
9686     static assert(is(Unshared!SharedIntPtr == shared(int)*));
9687 
9688     // shared(int)* -> shared(int)*
9689     alias PtrToSharedInt = shared(int)*;
9690     static assert(is(Unshared!PtrToSharedInt == shared(int)*));
9691 
9692     // immutable is unaffected
9693     alias ImmutableArr = immutable(int[]);
9694     static assert(is(Unshared!ImmutableArr == immutable(int[])));
9695 
9696     static struct S
9697     {
9698         int* ptr;
9699         const int* cPtr;
9700         shared int* sPtr;
9701     }
9702 
9703     shared S s;
9704     static assert(is(typeof(s) == shared S));
9705     static assert(is(typeof(typeof(s).ptr) == shared int*));
9706     static assert(is(typeof(typeof(s).cPtr) == const shared int*));
9707     static assert(is(typeof(typeof(s).sPtr) == shared int*));
9708 
9709     // For user-defined types, if shared is applied to a member variable only
9710     // because the containing type is shared, then shared is removed from that
9711     // member variable, but if the member variable is directly marked as shared,
9712     // then it continues to be shared.
9713 
9714     // shared S -> S
9715     static assert(is(Unshared!(typeof(s)) == S));
9716     static assert(is(typeof(Unshared!(typeof(s)).ptr) == int*));
9717     static assert(is(typeof(Unshared!(typeof(s)).cPtr) == const int*));
9718     static assert(is(typeof(Unshared!(typeof(s)).sPtr) == shared int*));
9719 
9720     static struct Foo(T)
9721     {
9722         T* ptr;
9723     }
9724 
9725     // The qualifier on the type is removed, but the qualifier on the template
9726     // argument is not.
9727     static assert(is(Unshared!(shared(Foo!(shared int))) == Foo!(shared int)));
9728     static assert(is(Unshared!(Foo!(shared int)) == Foo!(shared int)));
9729     static assert(is(Unshared!(shared(Foo!int)) == Foo!int));
9730 }
9731 
9732 /++
9733     Removes the outer layer of all type qualifiers from type $(D T) - this
9734     includes $(D shared).
9735 
9736     If no type qualifiers have been applied to the outer layer of type $(D T),
9737     then the result is $(D T).
9738 
9739     For the built-in scalar types (that is $(D bool), the character types, and
9740     the numeric types), they only have one layer, so $(D const U) simply becomes
9741     $(D U).
9742 
9743     Where the layers come in is pointers and arrays. $(D const(U*)) becomes
9744     $(D const(U)*), and $(D const(U[])), becomes $(D const(U)[]). So, a pointer
9745     goes from being fully $(D const) to being a mutable pointer to $(D const),
9746     and a dynamic array goes from being fully $(D const) to being a mutable
9747     dynamic array of $(D const) elements. And if there are multiple layers of
9748     pointers or arrays, it's just that outer layer which is affected - e.g.
9749     $(D shared(U**)) would become $(D shared(U*)*).
9750 
9751     For user-defined types, the effect is that $(D const U) becomes $(D U), and
9752     how that affects member variables depends on the type of the member
9753     variable. If a member variable is explicitly marked with any qualifiers,
9754     then it will continue to have those qualifiers even after Unqualified has
9755     stripped all qualifiers from the containing type. However, if a qualifier
9756     was on the member variable only because the containing type had that
9757     qualifier, then when Unqualified removes the qualifier from the containing
9758     type, it is removed from the member variable as well.
9759 
9760     Also, Unqualified has no effect on what a templated type is instantiated
9761     with, so if a templated type is instantiated with a template argument which
9762     has a type qualifier, the template instantiation will not change.
9763 
9764     Note that in most cases, $(LREF Unconst) or $(LREF Unshared) should be used
9765     rather than Unqualified, because in most cases, code is not designed to
9766     work with $(D shared) and thus doing type checks which remove $(D shared)
9767     will allow $(D shared) types to pass template constraints when they won't
9768     actually work with the code. And when code is designed to work with
9769     $(D shared), it's often the case that the type checks need to take
9770     $(D const) into account in order to avoid accidentally mutating $(D const)
9771     data and violating the type system.
9772 
9773     In particular, historically, a lot of D code has used
9774     $(REF Unqual, std, traits) (which is equivalent to phobos.sys.traits'
9775     Unqualified) when the programmer's intent was to remove $(D const), and
9776     $(D shared) wasn't actually considered at all. And in such cases, the code
9777     really should use $(LREF Unconst) instead.
9778 
9779     But of course, if a template constraint or $(D static if) really needs to
9780     strip off both the mutability qualifiers and $(D shared) for what it's
9781     testing for, then that's what Unqualified is for. It's just that it's best
9782     practice to use $(LREF Unconst) when it's not clear that $(D shared) should
9783     be removed as well.
9784 
9785     Also, note that $(D is(immutable T == immutable U))) is equivalent to
9786     $(D is(Unqualified!T == Unqualified!U)) (using $(D immutable) converts
9787     $(D const), $(D inout), and $(D shared) to $(D immutable), whereas using
9788     Unqualified strips off all type qualifiers, but the resulting comparison is
9789     the same as long as $(D immutable) is used on both sides or Unqualified is
9790     used on both sides)). So, in cases where code needs to compare two types to
9791     see whether they're the same while ignoring all qualifiers, it's generally
9792     better to use $(D immutable) on both types rather than using Unqualfied on
9793     both types, since that avoids needing to instantiate a template, and those
9794     instantiations can really add up when a project has a lot of templates
9795     with template constraints, $(D static if)s, and other forms of conditional
9796     compilation that need to compare types.
9797   +/
9798 template Unqualified(T)
9799 {
9800     import core.internal.traits : CoreUnqualified = Unqual;
9801     alias Unqualified = CoreUnqualified!(T);
9802 }
9803 
9804 ///
9805 @safe unittest
9806 {
9807     static assert(is(Unqualified!(                   int) == int));
9808     static assert(is(Unqualified!(             const int) == int));
9809     static assert(is(Unqualified!(       inout       int) == int));
9810     static assert(is(Unqualified!(       inout const int) == int));
9811     static assert(is(Unqualified!(shared             int) == int));
9812     static assert(is(Unqualified!(shared       const int) == int));
9813     static assert(is(Unqualified!(shared inout       int) == int));
9814     static assert(is(Unqualified!(shared inout const int) == int));
9815     static assert(is(Unqualified!(         immutable int) == int));
9816 
9817     // Only the outer layer of immutable is removed.
9818     // immutable(int[]) -> immutable(int)[]
9819     alias ImmIntArr = immutable(int[]);
9820     static assert(is(Unqualified!ImmIntArr == immutable(int)[]));
9821 
9822     // Only the outer layer of const is removed.
9823     // const(int*) -> const(int)*
9824     alias ConstIntPtr = const(int*);
9825     static assert(is(Unqualified!ConstIntPtr == const(int)*));
9826 
9827     // const(int)* -> const(int)*
9828     alias PtrToConstInt = const(int)*;
9829     static assert(is(Unqualified!PtrToConstInt == const(int)*));
9830 
9831     // Only the outer layer of shared is removed.
9832     // shared(int*) -> shared(int)*
9833     alias SharedIntPtr = shared(int*);
9834     static assert(is(Unqualified!SharedIntPtr == shared(int)*));
9835 
9836     // shared(int)* -> shared(int)*
9837     alias PtrToSharedInt = shared(int)*;
9838     static assert(is(Unqualified!PtrToSharedInt == shared(int)*));
9839 
9840     // Both const and shared are removed from the outer layer.
9841     // shared const int[] -> shared(const(int))[]
9842     alias SharedConstIntArr = shared const(int[]);
9843     static assert(is(Unqualified!SharedConstIntArr == shared(const(int))[]));
9844 
9845     static struct S
9846     {
9847         int* ptr;
9848         const int* cPtr;
9849         shared int* sPtr;
9850     }
9851 
9852     shared const S s;
9853     static assert(is(typeof(s) == shared const S));
9854     static assert(is(typeof(typeof(s).ptr) == shared const int*));
9855     static assert(is(typeof(typeof(s).cPtr) == shared const int*));
9856     static assert(is(typeof(typeof(s).sPtr) == shared const int*));
9857 
9858     // For user-defined types, all qualifiers that are applied to member
9859     // variables only because the containing type has them are removed, but the
9860     // ones that are directly on those member variables remain.
9861 
9862     // shared const S -> S
9863     static assert(is(Unqualified!(typeof(s)) == S));
9864     static assert(is(typeof(Unqualified!(typeof(s)).ptr) == int*));
9865     static assert(is(typeof(Unqualified!(typeof(s)).cPtr) == const int*));
9866     static assert(is(typeof(Unqualified!(typeof(s)).sPtr) == shared int*));
9867 
9868     static struct Foo(T)
9869     {
9870         T* ptr;
9871     }
9872 
9873     // The qualifiers on the type are removed, but the qualifiers on the
9874     // template argument are not.
9875     static assert(is(Unqualified!(const(Foo!(const int))) == Foo!(const int)));
9876     static assert(is(Unqualified!(Foo!(const int)) == Foo!(const int)));
9877     static assert(is(Unqualified!(const(Foo!int)) == Foo!int));
9878 }
9879 
9880 /++
9881     Applies $(D const) to the given type.
9882 
9883     This is primarily useful in conjunction with templates that take a template
9884     predicate (such as many of the templates in phobos.sys.meta), since while in
9885     most cases, you can simply do $(D const T) or $(D const(T)) to make $(D T)
9886     $(D const), with something like $(REF Map, phobos, sys, meta), you need to
9887     pass a template to be applied.
9888 
9889     See_Also:
9890         $(LREF ImmutableOf)
9891         $(LREF InoutOf)
9892         $(LREF SharedOf)
9893   +/
9894 alias ConstOf(T) = const T;
9895 
9896 ///
9897 @safe unittest
9898 {
9899     static assert(is(ConstOf!int == const int));
9900     static assert(is(ConstOf!(const int) == const int));
9901     static assert(is(ConstOf!(inout int) == inout const int));
9902     static assert(is(ConstOf!(shared int) == const shared int));
9903 
9904     // Note that const has no effect on immutable.
9905     static assert(is(ConstOf!(immutable int) == immutable int));
9906 
9907     import phobos.sys.meta : AliasSeq, Map;
9908 
9909     alias Types = AliasSeq!(int, long,
9910                             bool*, ubyte[],
9911                             string, immutable(string));
9912     alias WithConst = Map!(ConstOf, Types);
9913     static assert(is(WithConst ==
9914                      AliasSeq!(const int, const long,
9915                                const(bool*), const(ubyte[]),
9916                                const(string), immutable(string))));
9917 }
9918 
9919 /++
9920     Applies $(D immutable) to the given type.
9921 
9922     This is primarily useful in conjunction with templates that take a template
9923     predicate (such as many of the templates in phobos.sys.meta), since while in
9924     most cases, you can simply do $(D immutable T) or $(D immutable(T)) to make
9925     $(D T) $(D immutable), with something like $(REF Map, phobos, sys, meta),
9926     you need to pass a template to be applied.
9927 
9928     See_Also:
9929         $(LREF ConstOf)
9930         $(LREF InoutOf)
9931         $(LREF SharedOf)
9932   +/
9933 alias ImmutableOf(T) = immutable T;
9934 
9935 ///
9936 @safe unittest
9937 {
9938     static assert(is(ImmutableOf!int == immutable int));
9939 
9940     // Note that immutable overrides const and inout.
9941     static assert(is(ImmutableOf!(const int) == immutable int));
9942     static assert(is(ImmutableOf!(inout int) == immutable int));
9943 
9944     // Note that immutable overrides shared, since immutable is implicitly
9945     // shared.
9946     static assert(is(ImmutableOf!(shared int) == immutable int));
9947 
9948     static assert(is(ImmutableOf!(immutable int) == immutable int));
9949 
9950     import phobos.sys.meta : AliasSeq, Map;
9951 
9952     alias Types = AliasSeq!(int, long,
9953                             bool*, ubyte[],
9954                             string, immutable(string));
9955     alias WithImmutable = Map!(ImmutableOf, Types);
9956     static assert(is(WithImmutable ==
9957                      AliasSeq!(immutable int, immutable long,
9958                                immutable(bool*), immutable(ubyte[]),
9959                                immutable(string), immutable(string))));
9960 }
9961 
9962 /++
9963     Applies $(D inout) to the given type.
9964 
9965     This is primarily useful in conjunction with templates that take a template
9966     predicate (such as many of the templates in phobos.sys.meta), since while in
9967     most cases, you can simply do $(D inout T) or $(D inout(T)) to make $(D T)
9968     $(D inout), with something like $(REF Map, phobos, sys, meta), you need to
9969     pass a template to be applied.
9970 
9971     See_Also:
9972         $(LREF ConstOf)
9973         $(LREF ImmutableOf)
9974         $(LREF SharedOf)
9975   +/
9976 alias InoutOf(T) = inout T;
9977 
9978 ///
9979 @safe unittest
9980 {
9981     static assert(is(InoutOf!int == inout int));
9982     static assert(is(InoutOf!(const int) == inout const int));
9983     static assert(is(InoutOf!(inout int) == inout int));
9984     static assert(is(InoutOf!(shared int) == inout shared int));
9985 
9986     // Note that inout has no effect on immutable.
9987     static assert(is(InoutOf!(immutable int) == immutable int));
9988 
9989     import phobos.sys.meta : AliasSeq, Map;
9990 
9991     alias Types = AliasSeq!(int, long,
9992                             bool*, ubyte[],
9993                             string, immutable(string));
9994     alias WithInout = Map!(InoutOf, Types);
9995     static assert(is(WithInout ==
9996                      AliasSeq!(inout int, inout long,
9997                                inout(bool*), inout(ubyte[]),
9998                                inout(string), immutable(string))));
9999 }
10000 
10001 /++
10002     Applies $(D shared) to the given type.
10003 
10004     This is primarily useful in conjunction with templates that take a template
10005     predicate (such as many of the templates in phobos.sys.meta), since while in
10006     most cases, you can simply do $(D shared T) or $(D shared(T)) to make $(D T)
10007     $(D shared), with something like $(REF Map, phobos, sys, meta), you need to
10008     pass a template to be applied.
10009 
10010     See_Also:
10011         $(LREF ConstOf)
10012         $(LREF ImmutableOf)
10013         $(LREF InoutOf)
10014   +/
10015 alias SharedOf(T) = shared T;
10016 
10017 ///
10018 @safe unittest
10019 {
10020     static assert(is(SharedOf!int == shared int));
10021     static assert(is(SharedOf!(const int) == const shared int));
10022     static assert(is(SharedOf!(inout int) == inout shared int));
10023     static assert(is(SharedOf!(shared int) == shared int));
10024 
10025     // Note that shared has no effect on immutable, since immutable is
10026     // implicitly shared.
10027     static assert(is(SharedOf!(immutable int) == immutable int));
10028 
10029     import phobos.sys.meta : AliasSeq, Map;
10030 
10031     alias Types = AliasSeq!(int, long,
10032                             bool*, ubyte[],
10033                             string, immutable(string));
10034     alias WithShared = Map!(SharedOf, Types);
10035     static assert(is(WithShared ==
10036                      AliasSeq!(shared int, shared long,
10037                                shared(bool*), shared(ubyte[]),
10038                                shared(string), immutable(string))));
10039 }
10040 
10041 // Needed for rvalueOf/lvalueOf because
10042 // "inout on return means inout must be on a parameter as well"
10043 private struct __InoutWorkaroundStruct {}
10044 
10045 /++
10046     Creates an lvalue or rvalue of type T to be used in conjunction with
10047     $(D is(typeof(...))) or
10048     $(DDSUBLINK spec/traits, compiles, $(D __traits(compiles, ...))).
10049 
10050     The idea is that some traits or other forms of conditional compilation need
10051     to verify that a particular piece of code compiles with an rvalue or an
10052     lvalue of a specific type, and these $(D @property) functions allow you to
10053     get an rvalue or lvalue of a specific type to use within an expression that
10054     is then tested to see whether it compiles.
10055 
10056     They're $(D @property) functions so that using $(D typeof) on them gives
10057     the return type rather than the type of the function.
10058 
10059     Note that these functions are $(I not) defined, so if they're actually used
10060     outside of type introspection, they'll result in linker errors. They're
10061     entirely for testing that a particular piece of code compiles with an rvalue
10062     or lvalue of the given type.
10063 
10064     The $(D __InoutWorkaroundStruct) parameter is entirely to make it so that
10065     these work when the given type has the $(D inout) qualifier, since the
10066     language requires that a function that returns an $(D inout) type also have
10067     an $(D inout) type as a parameter. It should just be ignored.
10068   +/
10069 @property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
10070 
10071 /++ Ditto +/
10072 @property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
10073 
10074 ///
10075 @safe unittest
10076 {
10077     static int foo(int);
10078     static assert(is(typeof(foo(lvalueOf!int)) == int));
10079     static assert(is(typeof(foo(rvalueOf!int)) == int));
10080 
10081     static bool bar(ref int);
10082     static assert(is(typeof(bar(lvalueOf!int)) == bool));
10083     static assert(!is(typeof(bar(rvalueOf!int))));
10084 
10085     static assert( is(typeof({ lvalueOf!int = 42; })));
10086     static assert(!is(typeof({ rvalueOf!int = 42; })));
10087 
10088     static struct S {}
10089     static assert( is(typeof({ lvalueOf!S = S.init; })));
10090     static assert(!is(typeof({ rvalueOf!S = S.init; })));
10091 
10092     static struct NoAssign
10093     {
10094         @disable void opAssign(ref NoAssign);
10095     }
10096     static assert(!is(typeof({ lvalueOf!NoAssign = NoAssign.init; })));
10097     static assert(!is(typeof({ rvalueOf!NoAssign = NoAssign.init; })));
10098 }
10099 
10100 @system unittest
10101 {
10102     import phobos.sys.meta : AliasSeq;
10103 
10104     void needLvalue(T)(ref T);
10105     static struct S {}
10106     int i;
10107     struct Nested { void f() { ++i; } }
10108 
10109     static foreach (T; AliasSeq!(int, const int, immutable int, inout int, string, S, Nested, Object))
10110     {
10111         static assert(!__traits(compiles, needLvalue(rvalueOf!T)));
10112         static assert( __traits(compiles, needLvalue(lvalueOf!T)));
10113         static assert(is(typeof(rvalueOf!T) == T));
10114         static assert(is(typeof(lvalueOf!T) == T));
10115     }
10116 
10117     static assert(!__traits(compiles, rvalueOf!int = 1));
10118     static assert( __traits(compiles, lvalueOf!byte = 127));
10119     static assert(!__traits(compiles, lvalueOf!byte = 128));
10120 }
10121 
10122 // We may want to add this as some sort of public test helper in the future in
10123 // whatever module would be appropriate for that.
10124 private template assertWithQualifiers(alias Pred, T, bool expected)
10125 {
10126     static assert(Pred!T == expected);
10127     static assert(Pred!(const T) == expected);
10128     static assert(Pred!(inout T) == expected);
10129     static assert(Pred!(immutable T) == expected);
10130     static assert(Pred!(shared T) == expected);
10131 
10132     static if (is(T == U*, U))
10133     {
10134         static assert(Pred!(const(U)*) == expected);
10135         static assert(Pred!(inout(U)*) == expected);
10136         static assert(Pred!(immutable(U)*) == expected);
10137         static assert(Pred!(shared(U)*) == expected);
10138     }
10139     else static if (is(T == U[], U))
10140     {
10141         static assert(Pred!(const(U)[]) == expected);
10142         static assert(Pred!(inout(U)[]) == expected);
10143         static assert(Pred!(immutable(U)[]) == expected);
10144         static assert(Pred!(shared(U)[]) == expected);
10145     }
10146     else static if (is(T == U[n], U, size_t n))
10147     {
10148         static assert(Pred!(const(U)[n]) == expected);
10149         static assert(Pred!(inout(U)[n]) == expected);
10150         static assert(Pred!(immutable(U)[n]) == expected);
10151         static assert(Pred!(shared(U)[n]) == expected);
10152     }
10153 }
10154 
10155 private template assertWithQualifiers(alias Pred)
10156 {
10157     alias assertWithQualifiers(T, bool expected) = .assertWithQualifiers!(Pred, T, expected);
10158 }
10159 
10160 @safe unittest
10161 {
10162     mixin assertWithQualifiers!(isPointer, int*, true);
10163     mixin assertWithQualifiers!(isPointer, int, false);
10164 
10165     alias test = assertWithQualifiers!isPointer;
10166     mixin test!(int*, true);
10167     mixin test!(int, false);
10168 }