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 ReturnType)
81               $(LREF ToFunctionType)
82     ))
83     $(TR $(TD Aggregate Type Traits) $(TD
84               $(LREF FieldNames)
85               $(LREF FieldSymbols)
86               $(LREF FieldTypes)
87               $(LREF hasComplexAssignment)
88               $(LREF hasComplexCopying)
89               $(LREF hasComplexDestruction)
90               $(LREF hasIndirections)
91     ))
92     $(TR $(TD General Types) $(TD
93               $(LREF KeyType)
94               $(LREF OriginalType)
95               $(LREF PropertyType)
96               $(LREF SymbolType)
97               $(LREF ValueType)
98     ))
99     $(TR $(TD Traits for removing type qualfiers) $(TD
100               $(LREF Unconst)
101               $(LREF Unshared)
102               $(LREF Unqualified)
103     ))
104     $(TR $(TD Type Constructors) $(TD
105               $(LREF ConstOf)
106               $(LREF ImmutableOf)
107               $(LREF InoutOf)
108               $(LREF SharedOf)
109     ))
110     $(TR $(TD Misc) $(TD
111               $(LREF defaultInit)
112               $(LREF EnumMembers)
113               $(LREF lvalueOf)
114               $(LREF rvalueOf)
115     ))
116     )
117 
118     Copyright: Copyright The D Language Foundation 2005 - 2024.
119     License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
120     Authors:   $(HTTP jmdavisprog.com, Jonathan M Davis)
121                $(HTTP digitalmars.com, Walter Bright),
122                Tomasz Stachowiak (`isExpressions`),
123                $(HTTP erdani.org, Andrei Alexandrescu),
124                Shin Fujishiro,
125                $(HTTP octarineparrot.com, Robert Clipsham),
126                $(HTTP klickverbot.at, David Nadlinger),
127                Kenji Hara,
128                Shoichi Kato
129     Source:    $(PHOBOSSRC phobos/sys/traits)
130 +/
131 module phobos.sys.traits;
132 
133 /++
134     Whether the given type is an "aggregate type" - i.e. a struct, class,
135     interface, or union. Enum types whose base type is an aggregate type are
136     also considered aggregate types.
137   +/
138 template isAggregateType(T)
139 {
140     static if (is(T == enum))
141         enum isAggregateType = isAggregateType!(OriginalType!T);
142     else
143         enum isAggregateType = is(T == struct) || is(T == class) || is(T == interface) || is(T == union);
144 }
145 
146 ///
147 @safe unittest
148 {
149     struct S {}
150     class C {}
151     interface I {}
152     union U {}
153 
154     static assert( isAggregateType!S);
155     static assert( isAggregateType!C);
156     static assert( isAggregateType!I);
157     static assert( isAggregateType!U);
158     static assert( isAggregateType!(const S));
159     static assert( isAggregateType!(shared C));
160 
161     static assert(!isAggregateType!int);
162     static assert(!isAggregateType!string);
163     static assert(!isAggregateType!(S*));
164     static assert(!isAggregateType!(C[]));
165     static assert(!isAggregateType!(I[string]));
166 
167     enum ES : S { a = S.init }
168     enum EC : C { a = C.init }
169     enum EI : I { a = I.init }
170     enum EU : U { a = U.init }
171 
172     static assert( isAggregateType!ES);
173     static assert( isAggregateType!EC);
174     static assert( isAggregateType!EI);
175     static assert( isAggregateType!EU);
176     static assert( isAggregateType!(const ES));
177     static assert( isAggregateType!(const EC));
178 }
179 
180 /++
181     Whether the given type is a dynamic array (or what is sometimes referred to
182     as a slice, since a dynamic array in D is a slice of memory).
183 
184     Note that this does not include implicit conversions or enum types. The
185     type itself must be a dynamic array.
186 
187     Remember that D's dynamic arrays are essentially:
188     ---
189     struct DynamicArray(T)
190     {
191         size_t length;
192         T* ptr;
193     }
194     ---
195     where $(D ptr) points to the first element in the array, and $(D length) is
196     the number of elements in the array.
197 
198     A dynamic array is not a pointer (unlike arrays in C/C++), and its elements
199     do not live inside the dynamic array itself. The dynamic array is simply a
200     slice of memory and does not own or manage its own memory. It can be a
201     slice of any piece of memory, including GC-allocated memory, the stack,
202     malloc-ed memory, etc. (with what kind of memory it is of course being
203     determined by how the dynamic array was created in the first place)
204     - though if you do any operations on it which end up requiring allocation
205     (e.g. appending to it if it doesn't have the capacity to expand in-place,
206     which it won't if it isn't a slice of GC-allocated memory), then that
207     reallocation will result in the dynamic array being a slice of newly
208     allocated, GC-backed memory (regardless of what it was a slice of before),
209     since it's the GC that deals with those allocations.
210 
211     As long as code just accesses the elements or members of the dynamic array
212     - or reduces its length so that it's a smaller slice - it will continue to
213     point to whatever block of memory it pointed to originally. And because the
214     GC makes sure that appending to a dynamic array does not stomp on the
215     memory of any other dynamic arrays, appending to a dynamic array will not
216     affect any other dynamic array which is a slice of that same block of
217     memory whether a reallocation occurs or not.
218 
219     Regardless, since what allocated the memory that the dynamic array is a
220     slice of is irrevelant to the type of the dynamic array, whether a given
221     type is a dynamic array has nothing to do with the kind of memory that's
222     backing it. A dynamic array which is a slice of a static array of $(D int)
223     is the the same type as a dynamic array of $(D int) allocated with $(D new)
224     - i.e. both are $(D int[]). So, this trait will not tell you anything about
225     what kind of memory a dynamic array is a slice of. It just tells you
226     whether the type is a dynamic array or not.
227 
228     If for some reason, it matters for a function what kind of memory backs one
229     of its parameters which is a dynamic array, or it needs to be made clear
230     whether the function will possibly cause that dynamic array to be
231     reallocated, then that needs to be indicated by the documentation and
232     cannot be enforced with a template constraint. A template constraint can
233     enforce that a type used with a template meets certain criteria (e.g. that
234     it's a dynamic array), but it cannot enforce anything about how the
235     template actually uses the type.
236 
237     However, it $(D is) possible to enforce that a function doesn't use any
238     operations on a dynamic array which might cause it to be reallocated by
239     marking that function as $(D @nogc).
240 
241     In most cases though, code can be written to not care what kind of memory
242     backs a dynamic array, because none of the operations on a dynamic array
243     actually care what kind of memory it's a slice of. It mostly just matters
244     when you need to track the lifetime of the memory, because it wasn't
245     allocated by the GC, or when it matters whether a dynamic array could be
246     reallocated or not (e.g. because the code needs to have that dynamic array
247     continue to point to the same block of memory).
248 
249     See_Also:
250         $(LREF isPointer)
251         $(LREF isStaticArray)
252         $(DDSUBLINK spec/arrays, , The language spec for arrays)
253   +/
254 enum isDynamicArray(T) = is(T == U[], U);
255 
256 ///
257 @safe unittest
258 {
259     // Some types which are dynamic arrays.
260     static assert( isDynamicArray!(int[]));
261     static assert( isDynamicArray!(const int[]));
262     static assert( isDynamicArray!(inout int[]));
263     static assert( isDynamicArray!(shared(int)[]));
264     static assert( isDynamicArray!string);
265 
266     static assert( isDynamicArray!(typeof([1, 2, 3])));
267     static assert( isDynamicArray!(typeof("dlang")));
268 
269     int[] arr;
270     static assert( isDynamicArray!(typeof(arr)));
271 
272     // Some types which aren't dynamic arrays.
273     static assert(!isDynamicArray!int);
274     static assert(!isDynamicArray!(int*));
275     static assert(!isDynamicArray!real);
276 
277     static struct S
278     {
279         int[] arr;
280     }
281     static assert(!isDynamicArray!S);
282 
283     // The struct itself isn't considered a dynamic array,
284     // but its member variable is when checked directly.
285     static assert( isDynamicArray!(typeof(S.arr)));
286 
287     // Static arrays.
288     static assert(!isDynamicArray!(int[5]));
289     static assert(!isDynamicArray!(const(int)[5]));
290 
291     int[2] sArr = [42, 97];
292     static assert(!isDynamicArray!(typeof(sArr)));
293 
294     // While a static array is not a dynamic array,
295     // a slice of a static array is a dynamic array.
296     static assert( isDynamicArray!(typeof(sArr[])));
297 
298     // Dynamic array of static arrays.
299     static assert( isDynamicArray!(long[3][]));
300 
301     // Static array of dynamic arrays.
302     static assert(!isDynamicArray!(long[][3]));
303 
304     // Associative array.
305     static assert(!isDynamicArray!(int[string]));
306 
307     // While typeof(null) gets treated as void[] in some contexts, it is
308     // distinct from void[] and is not considered to be a dynamic array.
309     static assert(!isDynamicArray!(typeof(null)));
310 
311     // However, naturally, if null is cast to a dynamic array, it's a
312     // dynamic array, since the cast forces the type.
313     static assert( isDynamicArray!(typeof(cast(int[]) null)));
314 
315     enum E : int[]
316     {
317         a = [1, 2, 3],
318     }
319 
320     // Enums do not count.
321     static assert(!isDynamicArray!E);
322 
323     static struct AliasThis
324     {
325         int[] arr;
326         alias this = arr;
327     }
328 
329     // Other implicit conversions do not count.
330     static assert(!isDynamicArray!AliasThis);
331 }
332 
333 @safe unittest
334 {
335     import phobos.sys.meta : Alias, AliasSeq;
336 
337     static struct AliasThis(T)
338     {
339         T member;
340         alias this = member;
341     }
342 
343     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
344     {
345         foreach (T; AliasSeq!(int[], char[], string, long[3][], double[string][]))
346         {
347             enum E : Q!T { a = Q!T.init }
348 
349             static assert( isDynamicArray!(Q!T));
350             static assert(!isDynamicArray!E);
351             static assert(!isDynamicArray!(AliasThis!(Q!T)));
352         }
353 
354         foreach (T; AliasSeq!(int, int[51], int[][2],
355                               char[][int][11], immutable char[13u],
356                               const(real)[1], const(real)[1][1], void[0]))
357         {
358             enum E : Q!T { a = Q!T.init }
359 
360             static assert(!isDynamicArray!(Q!T));
361             static assert(!isDynamicArray!E);
362             static assert(!isDynamicArray!(AliasThis!(Q!T)));
363         }
364     }
365 }
366 
367 /++
368     Whether type $(D T) is a static array.
369 
370     Note that this does not include implicit conversions or enum types. The
371     type itself must be a static array. This is in contrast to
372     $(D __traits(isStaticArray, T)) which is true for enums (but not for other
373     implict conversions to static arrays).
374 
375     As explained in the module documentation, traits like this one are not true
376     for enums (unlike most of the $(D __traits) traits) in order to avoid
377     testing for implicit conversions by default with template constraints,
378     since that tends to lead to subtle bugs when the code isn't carefully
379     written to take implicit conversions into account.
380 
381     See also:
382         $(DDSUBLINK spec/traits, isStaticArray, $(D __traits(isStaticArray, T)))
383         $(DDSUBLINK spec/arrays, , The language spec for arrays)
384   +/
385 enum isStaticArray(T) = is(T == U[n], U, size_t n);
386 
387 ///
388 @safe unittest
389 {
390     // Some types which are static arrays.
391     static assert( isStaticArray!(int[12]));
392     static assert( isStaticArray!(const int[42]));
393     static assert( isStaticArray!(inout int[0]));
394     static assert( isStaticArray!(shared(int)[907]));
395     static assert( isStaticArray!(immutable(char)[5]));
396 
397     // D doesn't have static array literals, but you get the same effect
398     // by casting a dynamic array literal to a static array, and of course,
399     // the result is typed as a static array.
400     static assert( isStaticArray!(typeof(cast(int[3]) [1, 2, 3])));
401 
402     int[2] sArr = [1, 2];
403     static assert( isStaticArray!(typeof(sArr)));
404 
405     // Some types which are not static arrays.
406     static assert(!isStaticArray!int);
407     static assert(!isStaticArray!(int*));
408     static assert(!isStaticArray!real);
409 
410     static struct S
411     {
412         int[4] arr;
413     }
414     static assert(!isStaticArray!S);
415 
416     // The struct itself isn't considered a static array,
417     // but its member variable is when checked directly.
418     static assert( isStaticArray!(typeof(S.arr)));
419 
420     // Dynamic arrays.
421     static assert(!isStaticArray!(int[]));
422     static assert(!isStaticArray!(const(int)[]));
423     static assert(!isStaticArray!string);
424 
425     int[] arr;
426     static assert(!isStaticArray!(typeof(arr)));
427 
428     // A slice of a static array is of course not a static array,
429     // because it's a dynamic array.
430     static assert(!isStaticArray!(typeof(sArr[])));
431 
432     // Static array of dynamic arrays.
433     static assert( isStaticArray!(long[][3]));
434 
435     // Dynamic array of static arrays.
436     static assert(!isStaticArray!(long[3][]));
437 
438     // Associative array.
439     static assert(!isStaticArray!(int[string]));
440 
441     // Of course, null is not considered to be a static array.
442     static assert(!isStaticArray!(typeof(null)));
443 
444     enum E : int[3]
445     {
446         a = [1, 2, 3],
447     }
448 
449     // Enums do not count.
450     static assert(!isStaticArray!E);
451 
452     // This is where isStaticArray differs from __traits(isStaticArray, ...)
453     static assert( __traits(isStaticArray, E));
454 
455     static struct AliasThis
456     {
457         int[] arr;
458         alias this = arr;
459     }
460 
461     // Other implicit conversions do not count.
462     static assert(!isStaticArray!AliasThis);
463 
464     static assert(!__traits(isStaticArray, AliasThis));
465 }
466 
467 @safe unittest
468 {
469     import phobos.sys.meta : Alias, AliasSeq;
470 
471     static struct AliasThis(T)
472     {
473         T member;
474         alias this = member;
475     }
476 
477     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
478     {
479         foreach (T; AliasSeq!(int[51], int[][2],
480                               char[][int][11], immutable char[13u],
481                               const(real)[1], const(real)[1][1], void[0]))
482         {
483             enum E : Q!T { a = Q!T.init, }
484 
485             static assert( isStaticArray!(Q!T));
486             static assert(!isStaticArray!E);
487             static assert(!isStaticArray!(AliasThis!(Q!T)));
488         }
489 
490         foreach (T; AliasSeq!(int, int[], char[], string, long[3][], double[string][]))
491         {
492             enum E : Q!T { a = Q!T.init, }
493 
494             static assert(!isStaticArray!(Q!T));
495             static assert(!isStaticArray!E);
496             static assert(!isStaticArray!(AliasThis!(Q!T)));
497         }
498     }
499 }
500 
501 /++
502     Whether the given type is one of the built-in integer types, ignoring all
503     qualifiers.
504 
505     $(TABLE
506         $(TR $(TH Integer Types))
507         $(TR $(TD byte))
508         $(TR $(TD ubyte))
509         $(TR $(TD short))
510         $(TR $(TD ushort))
511         $(TR $(TD int))
512         $(TR $(TD uint))
513         $(TR $(TD long))
514         $(TR $(TD ulong))
515     )
516 
517     Note that this does not include implicit conversions or enum types. The
518     type itself must be one of the built-in integer types.
519 
520     This trait does have some similarities with $(D __traits(isIntegral, T)),
521     but $(D isIntegral) accepts a $(I lot) more types than isInteger does.
522     isInteger is specifically for testing for the built-in integer types,
523     whereas $(D isIntegral) tests for a whole set of types that are vaguely
524     integer-like (including $(D bool), the three built-in character types, and
525     some of the vector types from core.simd). So, for most code, isInteger is
526     going to be more appropriate, but obviously, it depends on what the code is
527     trying to do.
528 
529     See also:
530         $(DDSUBLINK spec/traits, isIntegral, $(D __traits(isIntegral, T)))
531         $(LREF isFloatingPoint)
532         $(LREF isSignedInteger)
533         $(LREF isNumeric)
534         $(LREF isUnsignedInteger)
535   +/
536 enum isInteger(T) = is(immutable T == immutable byte) ||
537                     is(immutable T == immutable ubyte) ||
538                     is(immutable T == immutable short) ||
539                     is(immutable T == immutable ushort) ||
540                     is(immutable T == immutable int) ||
541                     is(immutable T == immutable uint) ||
542                     is(immutable T == immutable long) ||
543                     is(immutable T == immutable ulong);
544 
545 ///
546 @safe unittest
547 {
548     // Some types which are integer types.
549     static assert( isInteger!byte);
550     static assert( isInteger!ubyte);
551     static assert( isInteger!short);
552     static assert( isInteger!ushort);
553     static assert( isInteger!int);
554     static assert( isInteger!uint);
555     static assert( isInteger!long);
556     static assert( isInteger!ulong);
557 
558     static assert( isInteger!(const ubyte));
559     static assert( isInteger!(immutable short));
560     static assert( isInteger!(inout int));
561     static assert( isInteger!(shared uint));
562     static assert( isInteger!(const shared ulong));
563 
564     static assert( isInteger!(typeof(42)));
565     static assert( isInteger!(typeof(1234567890L)));
566 
567     int i;
568     static assert( isInteger!(typeof(i)));
569 
570     // Some types which aren't integer types.
571     static assert(!isInteger!bool);
572     static assert(!isInteger!char);
573     static assert(!isInteger!wchar);
574     static assert(!isInteger!dchar);
575     static assert(!isInteger!(int[]));
576     static assert(!isInteger!(ubyte[4]));
577     static assert(!isInteger!(int*));
578     static assert(!isInteger!double);
579     static assert(!isInteger!string);
580 
581     static struct S
582     {
583         int i;
584     }
585     static assert(!isInteger!S);
586 
587     // The struct itself isn't considered an integer,
588     // but its member variable is when checked directly.
589     static assert( isInteger!(typeof(S.i)));
590 
591     enum E : int
592     {
593         a = 42
594     }
595 
596     // Enums do not count.
597     static assert(!isInteger!E);
598 
599     static struct AliasThis
600     {
601         int i;
602         alias this = i;
603     }
604 
605     // Other implicit conversions do not count.
606     static assert(!isInteger!AliasThis);
607 }
608 
609 @safe unittest
610 {
611     import phobos.sys.meta : Alias, AliasSeq;
612 
613     static struct AliasThis(T)
614     {
615         T member;
616         alias this = member;
617     }
618 
619     // The actual core.simd types available vary from system to system, so we
620     // have to be a bit creative here. The reason that we're testing these types
621     // is because __traits(isIntegral, T) accepts them, but isInteger is not
622     // supposed to.
623     template SIMDTypes()
624     {
625         import core.simd;
626 
627         alias SIMDTypes = AliasSeq!();
628         static if (is(ubyte16))
629             SIMDTypes = AliasSeq!(SIMDTypes, ubyte16);
630         static if (is(int4))
631             SIMDTypes = AliasSeq!(SIMDTypes, int4);
632         static if (is(double2))
633             SIMDTypes = AliasSeq!(SIMDTypes, double2);
634         static if (is(void16))
635             SIMDTypes = AliasSeq!(SIMDTypes, void16);
636     }
637 
638     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
639     {
640         foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
641         {
642             enum E : Q!T { a = Q!T.init }
643 
644             static assert( isInteger!(Q!T));
645             static assert(!isInteger!E);
646             static assert(!isInteger!(AliasThis!(Q!T)));
647         }
648 
649         foreach (T; AliasSeq!(bool, char, wchar, dchar, float, double, real, SIMDTypes!(),
650                               int[], ubyte[8], dchar[], void[], long*))
651         {
652             enum E : Q!T { a = Q!T.init }
653 
654             static assert(!isInteger!(Q!T));
655             static assert(!isInteger!E);
656             static assert(!isInteger!(AliasThis!(Q!T)));
657         }
658     }
659 }
660 
661 /++
662     Whether the given type is one of the built-in signed integer types, ignoring
663     all qualifiers.
664 
665     $(TABLE
666         $(TR $(TH Signed Integer Types))
667         $(TR $(TD byte))
668         $(TR $(TD short))
669         $(TR $(TD int))
670         $(TR $(TD long))
671     )
672 
673     Note that this does not include implicit conversions or enum types. The
674     type itself must be one of the built-in signed integer types.
675 
676     See also:
677         $(LREF isFloatingPoint)
678         $(LREF isInteger)
679         $(LREF isNumeric)
680         $(LREF isUnsignedInteger)
681   +/
682 enum isSignedInteger(T) = is(immutable T == immutable byte) ||
683                           is(immutable T == immutable short) ||
684                           is(immutable T == immutable int) ||
685                           is(immutable T == immutable long);
686 
687 ///
688 @safe unittest
689 {
690     // Some types which are signed integer types.
691     static assert( isSignedInteger!byte);
692     static assert( isSignedInteger!short);
693     static assert( isSignedInteger!int);
694     static assert( isSignedInteger!long);
695 
696     static assert( isSignedInteger!(const byte));
697     static assert( isSignedInteger!(immutable short));
698     static assert( isSignedInteger!(inout int));
699     static assert( isSignedInteger!(shared int));
700     static assert( isSignedInteger!(const shared long));
701 
702     static assert( isSignedInteger!(typeof(42)));
703     static assert( isSignedInteger!(typeof(1234567890L)));
704 
705     int i;
706     static assert( isSignedInteger!(typeof(i)));
707 
708     // Some types which aren't signed integer types.
709     static assert(!isSignedInteger!ubyte);
710     static assert(!isSignedInteger!ushort);
711     static assert(!isSignedInteger!uint);
712     static assert(!isSignedInteger!ulong);
713 
714     static assert(!isSignedInteger!bool);
715     static assert(!isSignedInteger!char);
716     static assert(!isSignedInteger!wchar);
717     static assert(!isSignedInteger!dchar);
718     static assert(!isSignedInteger!(int[]));
719     static assert(!isSignedInteger!(ubyte[4]));
720     static assert(!isSignedInteger!(int*));
721     static assert(!isSignedInteger!double);
722     static assert(!isSignedInteger!string);
723 
724     static struct S
725     {
726         int i;
727     }
728     static assert(!isSignedInteger!S);
729 
730     // The struct itself isn't considered a signed integer,
731     // but its member variable is when checked directly.
732     static assert( isSignedInteger!(typeof(S.i)));
733 
734     enum E : int
735     {
736         a = 42
737     }
738 
739     // Enums do not count.
740     static assert(!isSignedInteger!E);
741 
742     static struct AliasThis
743     {
744         int i;
745         alias this = i;
746     }
747 
748     // Other implicit conversions do not count.
749     static assert(!isSignedInteger!AliasThis);
750 }
751 
752 @safe unittest
753 {
754     import phobos.sys.meta : Alias, AliasSeq;
755 
756     static struct AliasThis(T)
757     {
758         T member;
759         alias this = member;
760     }
761 
762     // The actual core.simd types available vary from system to system, so we
763     // have to be a bit creative here. The reason that we're testing these types
764     // is because __traits(isIntegral, T) accepts them, but isSignedInteger is
765     // not supposed to.
766     template SIMDTypes()
767     {
768         import core.simd;
769 
770         alias SIMDTypes = AliasSeq!();
771         static if (is(ubyte16))
772             SIMDTypes = AliasSeq!(SIMDTypes, ubyte16);
773         static if (is(int4))
774             SIMDTypes = AliasSeq!(SIMDTypes, int4);
775         static if (is(double2))
776             SIMDTypes = AliasSeq!(SIMDTypes, double2);
777         static if (is(void16))
778             SIMDTypes = AliasSeq!(SIMDTypes, void16);
779     }
780 
781     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
782     {
783         foreach (T; AliasSeq!(byte, short, int, long))
784         {
785             enum E : Q!T { a = Q!T.init }
786 
787             static assert( isSignedInteger!(Q!T));
788             static assert(!isSignedInteger!E);
789             static assert(!isSignedInteger!(AliasThis!(Q!T)));
790         }
791 
792         foreach (T; AliasSeq!(ubyte, ushort, uint, ulong,
793                               bool, char, wchar, dchar, float, double, real, SIMDTypes!(),
794                               int[], ubyte[8], dchar[], void[], long*))
795         {
796             enum E : Q!T { a = Q!T.init }
797 
798             static assert(!isSignedInteger!(Q!T));
799             static assert(!isSignedInteger!E);
800             static assert(!isSignedInteger!(AliasThis!(Q!T)));
801         }
802     }
803 }
804 
805 /++
806     Whether the given type is one of the built-in unsigned integer types,
807     ignoring all qualifiers.
808 
809     $(TABLE
810         $(TR $(TH Integer Types))
811         $(TR $(TD ubyte))
812         $(TR $(TD ushort))
813         $(TR $(TD uint))
814         $(TR $(TD ulong))
815     )
816 
817     Note that this does not include implicit conversions or enum types. The
818     type itself must be one of the built-in unsigned integer types.
819 
820     This trait does have some similarities with $(D __traits(isUnsigned, T)),
821     but $(D isUnsigned) accepts a $(I lot) more types than isUnsignedInteger
822     does. isUnsignedInteger is specifically for testing for the built-in
823     unsigned integer types, whereas $(D isUnsigned) tests for a whole set of
824     types that are unsigned and vaguely integer-like (including $(D bool), the
825     three built-in character types, and some of the vector types from
826     core.simd). So, for most code, isUnsignedInteger is going to be more
827     appropriate, but obviously, it depends on what the code is trying to do.
828 
829     See also:
830         $(DDSUBLINK spec/traits, isUnsigned, $(D __traits(isUnsigned, T)))
831         $(LREF isFloatingPoint)
832         $(LREF isInteger)
833         $(LREF isSignedInteger)
834         $(LREF isNumeric)
835   +/
836 enum isUnsignedInteger(T) = is(immutable T == immutable ubyte) ||
837                             is(immutable T == immutable ushort) ||
838                             is(immutable T == immutable uint) ||
839                             is(immutable T == immutable ulong);
840 
841 ///
842 @safe unittest
843 {
844     // Some types which are unsigned integer types.
845     static assert( isUnsignedInteger!ubyte);
846     static assert( isUnsignedInteger!ushort);
847     static assert( isUnsignedInteger!uint);
848     static assert( isUnsignedInteger!ulong);
849 
850     static assert( isUnsignedInteger!(const ubyte));
851     static assert( isUnsignedInteger!(immutable ushort));
852     static assert( isUnsignedInteger!(inout uint));
853     static assert( isUnsignedInteger!(shared uint));
854     static assert( isUnsignedInteger!(const shared ulong));
855 
856     static assert( isUnsignedInteger!(typeof(42u)));
857     static assert( isUnsignedInteger!(typeof(1234567890UL)));
858 
859     uint u;
860     static assert( isUnsignedInteger!(typeof(u)));
861 
862     // Some types which aren't unsigned integer types.
863     static assert(!isUnsignedInteger!byte);
864     static assert(!isUnsignedInteger!short);
865     static assert(!isUnsignedInteger!int);
866     static assert(!isUnsignedInteger!long);
867 
868     static assert(!isUnsignedInteger!bool);
869     static assert(!isUnsignedInteger!char);
870     static assert(!isUnsignedInteger!wchar);
871     static assert(!isUnsignedInteger!dchar);
872     static assert(!isUnsignedInteger!(int[]));
873     static assert(!isUnsignedInteger!(ubyte[4]));
874     static assert(!isUnsignedInteger!(int*));
875     static assert(!isUnsignedInteger!double);
876     static assert(!isUnsignedInteger!string);
877 
878     static struct S
879     {
880         uint u;
881     }
882     static assert(!isUnsignedInteger!S);
883 
884     // The struct itself isn't considered an unsigned integer,
885     // but its member variable is when checked directly.
886     static assert( isUnsignedInteger!(typeof(S.u)));
887 
888     enum E : uint
889     {
890         a = 42
891     }
892 
893     // Enums do not count.
894     static assert(!isUnsignedInteger!E);
895 
896     static struct AliasThis
897     {
898         uint u;
899         alias this = u;
900     }
901 
902     // Other implicit conversions do not count.
903     static assert(!isUnsignedInteger!AliasThis);
904 }
905 
906 @safe unittest
907 {
908     import phobos.sys.meta : Alias, AliasSeq;
909 
910     static struct AliasThis(T)
911     {
912         T member;
913         alias this = member;
914     }
915 
916     // The actual core.simd types available vary from system to system, so we
917     // have to be a bit creative here. The reason that we're testing these types
918     // is because __traits(isIntegral, T) and __traits(isUnsigned, T) accept
919     // them, but isUnsignedInteger is not supposed to.
920     template SIMDTypes()
921     {
922         import core.simd;
923 
924         alias SIMDTypes = AliasSeq!();
925         static if (is(ubyte16))
926             SIMDTypes = AliasSeq!(SIMDTypes, ubyte16);
927         static if (is(int4))
928             SIMDTypes = AliasSeq!(SIMDTypes, int4);
929         static if (is(double2))
930             SIMDTypes = AliasSeq!(SIMDTypes, double2);
931         static if (is(void16))
932             SIMDTypes = AliasSeq!(SIMDTypes, void16);
933     }
934 
935     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
936     {
937         foreach (T; AliasSeq!(ubyte, ushort, uint, ulong))
938         {
939             enum E : Q!T { a = Q!T.init }
940 
941             static assert( isUnsignedInteger!(Q!T));
942             static assert(!isUnsignedInteger!E);
943             static assert(!isUnsignedInteger!(AliasThis!(Q!T)));
944         }
945 
946         foreach (T; AliasSeq!(byte, short, int, long,
947                               bool, char, wchar, dchar, float, double, real, SIMDTypes!(),
948                               int[], ubyte[8], dchar[], void[], long*))
949         {
950             enum E : Q!T { a = Q!T.init }
951 
952             static assert(!isUnsignedInteger!(Q!T));
953             static assert(!isUnsignedInteger!E);
954             static assert(!isUnsignedInteger!(AliasThis!(Q!T)));
955         }
956     }
957 }
958 
959 /++
960     Whether the given type is one of the built-in floating-point types, ignoring
961     all qualifiers.
962 
963     $(TABLE
964         $(TR $(TH Floating-Point Types))
965         $(TR $(TD float))
966         $(TR $(TD double))
967         $(TR $(TD real))
968     )
969 
970     Note that this does not include implicit conversions or enum types. The
971     type itself must be one of the built-in floating-point types.
972 
973     This trait does have some similarities with $(D __traits(isFloating, T)),
974     but $(D isFloating) accepts more types than isFloatingPoint does.
975     isFloatingPoint is specifically for testing for the built-in floating-point
976     types, whereas $(D isFloating) tests for a whole set of types that are
977     vaguely float-like (including enums with a base type which is a
978     floating-point type and some of the vector types from core.simd). So, for
979     most code, isFloatingPoint is going to be more appropriate, but obviously,
980     it depends on what the code is trying to do.
981 
982     See also:
983         $(DDSUBLINK spec/traits, isFloating, $(D __traits(isFloating, T)))
984         $(LREF isInteger)
985         $(LREF isSignedInteger)
986         $(LREF isNumeric)
987         $(LREF isUnsignedInteger)
988   +/
989 enum isFloatingPoint(T) = is(immutable T == immutable float) ||
990                           is(immutable T == immutable double) ||
991                           is(immutable T == immutable real);
992 
993 ///
994 @safe unittest
995 {
996     // Some types which are floating-point types.
997     static assert( isFloatingPoint!float);
998     static assert( isFloatingPoint!double);
999     static assert( isFloatingPoint!real);
1000 
1001     static assert( isFloatingPoint!(const float));
1002     static assert( isFloatingPoint!(immutable float));
1003     static assert( isFloatingPoint!(inout double));
1004     static assert( isFloatingPoint!(shared double));
1005     static assert( isFloatingPoint!(const shared real));
1006 
1007     static assert( isFloatingPoint!(typeof(42.0)));
1008     static assert( isFloatingPoint!(typeof(42f)));
1009     static assert( isFloatingPoint!(typeof(1e5)));
1010     static assert( isFloatingPoint!(typeof(97.4L)));
1011 
1012     double d;
1013     static assert( isFloatingPoint!(typeof(d)));
1014 
1015     // Some types which aren't floating-point types.
1016     static assert(!isFloatingPoint!bool);
1017     static assert(!isFloatingPoint!char);
1018     static assert(!isFloatingPoint!dchar);
1019     static assert(!isFloatingPoint!int);
1020     static assert(!isFloatingPoint!long);
1021     static assert(!isFloatingPoint!(float[]));
1022     static assert(!isFloatingPoint!(double[4]));
1023     static assert(!isFloatingPoint!(real*));
1024     static assert(!isFloatingPoint!string);
1025 
1026     static struct S
1027     {
1028         double d;
1029     }
1030     static assert(!isFloatingPoint!S);
1031 
1032     // The struct itself isn't considered a floating-point type,
1033     // but its member variable is when checked directly.
1034     static assert( isFloatingPoint!(typeof(S.d)));
1035 
1036     enum E : double
1037     {
1038         a = 12.34
1039     }
1040 
1041     // Enums do not count.
1042     static assert(!isFloatingPoint!E);
1043 
1044     static struct AliasThis
1045     {
1046         double d;
1047         alias this = d;
1048     }
1049 
1050     // Other implicit conversions do not count.
1051     static assert(!isFloatingPoint!AliasThis);
1052 }
1053 
1054 @safe unittest
1055 {
1056     import phobos.sys.meta : Alias, AliasSeq;
1057 
1058     static struct AliasThis(T)
1059     {
1060         T member;
1061         alias this = member;
1062     }
1063 
1064     // The actual core.simd types available vary from system to system, so we
1065     // have to be a bit creative here. The reason that we're testing these types
1066     // is because __traits(isFloating, T) accepts them, but isFloatingPoint is
1067     // not supposed to.
1068     template SIMDTypes()
1069     {
1070         import core.simd;
1071 
1072         alias SIMDTypes = AliasSeq!();
1073         static if (is(int4))
1074             SIMDTypes = AliasSeq!(SIMDTypes, int4);
1075         static if (is(double2))
1076             SIMDTypes = AliasSeq!(SIMDTypes, double2);
1077         static if (is(void16))
1078             SIMDTypes = AliasSeq!(SIMDTypes, void16);
1079     }
1080 
1081     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
1082     {
1083         foreach (T; AliasSeq!(float, double, real))
1084         {
1085             enum E : Q!T { a = Q!T.init }
1086 
1087             static assert( isFloatingPoint!(Q!T));
1088             static assert(!isFloatingPoint!E);
1089             static assert(!isFloatingPoint!(AliasThis!(Q!T)));
1090         }
1091 
1092         foreach (T; AliasSeq!(bool, char, wchar, dchar, byte, ubyte, short, ushort,
1093                               int, uint, long, ulong, SIMDTypes!(),
1094                               int[], float[8], real[], void[], double*))
1095         {
1096             enum E : Q!T { a = Q!T.init }
1097 
1098             static assert(!isFloatingPoint!(Q!T));
1099             static assert(!isFloatingPoint!E);
1100             static assert(!isFloatingPoint!(AliasThis!(Q!T)));
1101         }
1102     }
1103 }
1104 
1105 /++
1106     Whether the given type is one of the built-in numeric types, ignoring all
1107     qualifiers. It's equivalent to $(D isInteger!T || isFloatingPoint!T), but
1108     it only involves a single template instantation instead of two.
1109 
1110     $(TABLE
1111         $(TR $(TH Numeric Types))
1112         $(TR $(TD byte))
1113         $(TR $(TD ubyte))
1114         $(TR $(TD short))
1115         $(TR $(TD ushort))
1116         $(TR $(TD int))
1117         $(TR $(TD uint))
1118         $(TR $(TD long))
1119         $(TR $(TD ulong))
1120         $(TR $(TD float))
1121         $(TR $(TD double))
1122         $(TR $(TD real))
1123     )
1124 
1125     Note that this does not include implicit conversions or enum types. The
1126     type itself must be one of the built-in numeric types.
1127 
1128     See_Also:
1129         $(LREF isFloatingPoint)
1130         $(LREF isInteger)
1131         $(LREF isSignedInteger)
1132         $(LREF isUnsignedInteger)
1133   +/
1134 enum isNumeric(T) = is(immutable T == immutable byte) ||
1135                     is(immutable T == immutable ubyte) ||
1136                     is(immutable T == immutable short) ||
1137                     is(immutable T == immutable ushort) ||
1138                     is(immutable T == immutable int) ||
1139                     is(immutable T == immutable uint) ||
1140                     is(immutable T == immutable long) ||
1141                     is(immutable T == immutable ulong) ||
1142                     is(immutable T == immutable float) ||
1143                     is(immutable T == immutable double) ||
1144                     is(immutable T == immutable real);
1145 
1146 ///
1147 @safe unittest
1148 {
1149     // Some types which are numeric types.
1150     static assert( isNumeric!byte);
1151     static assert( isNumeric!ubyte);
1152     static assert( isNumeric!short);
1153     static assert( isNumeric!ushort);
1154     static assert( isNumeric!int);
1155     static assert( isNumeric!uint);
1156     static assert( isNumeric!long);
1157     static assert( isNumeric!ulong);
1158     static assert( isNumeric!float);
1159     static assert( isNumeric!double);
1160     static assert( isNumeric!real);
1161 
1162     static assert( isNumeric!(const short));
1163     static assert( isNumeric!(immutable int));
1164     static assert( isNumeric!(inout uint));
1165     static assert( isNumeric!(shared long));
1166     static assert( isNumeric!(const shared real));
1167 
1168     static assert( isNumeric!(typeof(42)));
1169     static assert( isNumeric!(typeof(1234657890L)));
1170     static assert( isNumeric!(typeof(42.0)));
1171     static assert( isNumeric!(typeof(42f)));
1172     static assert( isNumeric!(typeof(1e5)));
1173     static assert( isNumeric!(typeof(97.4L)));
1174 
1175     int i;
1176     static assert( isNumeric!(typeof(i)));
1177 
1178     // Some types which aren't numeric types.
1179     static assert(!isNumeric!bool);
1180     static assert(!isNumeric!char);
1181     static assert(!isNumeric!dchar);
1182     static assert(!isNumeric!(int[]));
1183     static assert(!isNumeric!(double[4]));
1184     static assert(!isNumeric!(real*));
1185     static assert(!isNumeric!string);
1186 
1187     static struct S
1188     {
1189         int i;
1190     }
1191     static assert(!isNumeric!S);
1192 
1193     // The struct itself isn't considered a numeric type,
1194     // but its member variable is when checked directly.
1195     static assert( isNumeric!(typeof(S.i)));
1196 
1197     enum E : int
1198     {
1199         a = 42
1200     }
1201 
1202     // Enums do not count.
1203     static assert(!isNumeric!E);
1204 
1205     static struct AliasThis
1206     {
1207         int i;
1208         alias this = i;
1209     }
1210 
1211     // Other implicit conversions do not count.
1212     static assert(!isNumeric!AliasThis);
1213 }
1214 
1215 @safe unittest
1216 {
1217     import phobos.sys.meta : Alias, AliasSeq;
1218 
1219     static struct AliasThis(T)
1220     {
1221         T member;
1222         alias this = member;
1223     }
1224 
1225     // The actual core.simd types available vary from system to system, so we
1226     // have to be a bit creative here. The reason that we're testing these types
1227     // is because __traits(isInteger, T) and __traits(isFloating, T) accept
1228     // them, but isNumeric is not supposed to.
1229     template SIMDTypes()
1230     {
1231         import core.simd;
1232 
1233         alias SIMDTypes = AliasSeq!();
1234         static if (is(int4))
1235             SIMDTypes = AliasSeq!(SIMDTypes, int4);
1236         static if (is(double2))
1237             SIMDTypes = AliasSeq!(SIMDTypes, double2);
1238         static if (is(void16))
1239             SIMDTypes = AliasSeq!(SIMDTypes, void16);
1240     }
1241 
1242     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
1243     {
1244         foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong, float, double, real))
1245         {
1246             enum E : Q!T { a = Q!T.init }
1247 
1248             static assert( isNumeric!(Q!T));
1249             static assert(!isNumeric!E);
1250             static assert(!isNumeric!(AliasThis!(Q!T)));
1251         }
1252 
1253         foreach (T; AliasSeq!(bool, char, wchar, dchar, SIMDTypes!(),
1254                               int[], float[8], real[], void[], double*))
1255         {
1256             enum E : Q!T { a = Q!T.init }
1257 
1258             static assert(!isNumeric!(Q!T));
1259             static assert(!isNumeric!E);
1260             static assert(!isNumeric!(AliasThis!(Q!T)));
1261         }
1262     }
1263 }
1264 
1265 /++
1266     Whether the given type is a pointer.
1267 
1268     Note that this does not include implicit conversions or enum types. The
1269     type itself must be a pointer.
1270 
1271     Also, remember that unlike C/C++, D's arrays are not pointers. Rather, a
1272     dynamic array in D is a slice of memory which has a member which is a
1273     pointer to its first element and another member which is the length of the
1274     array as $(D size_t). So, a dynamic array / slice has a $(D ptr) member
1275     which is a pointer, but the dynamic array itself is not a pointer.
1276 
1277     See_Also:
1278         $(LREF isDynamicArray)
1279   +/
1280 enum isPointer(T) = is(T == U*, U);
1281 
1282 ///
1283 @system unittest
1284 {
1285     // Some types which are pointers.
1286     static assert( isPointer!(bool*));
1287     static assert( isPointer!(int*));
1288     static assert( isPointer!(int**));
1289     static assert( isPointer!(real*));
1290     static assert( isPointer!(string*));
1291 
1292     static assert( isPointer!(const int*));
1293     static assert( isPointer!(immutable int*));
1294     static assert( isPointer!(inout int*));
1295     static assert( isPointer!(shared int*));
1296     static assert( isPointer!(const shared int*));
1297 
1298     static assert( isPointer!(typeof("foobar".ptr)));
1299 
1300     int* ptr;
1301     static assert( isPointer!(typeof(ptr)));
1302 
1303     int i;
1304     static assert( isPointer!(typeof(&i)));
1305 
1306     // Some types which aren't pointers.
1307     static assert(!isPointer!bool);
1308     static assert(!isPointer!int);
1309     static assert(!isPointer!dchar);
1310     static assert(!isPointer!(int[]));
1311     static assert(!isPointer!(double[4]));
1312     static assert(!isPointer!string);
1313 
1314     static struct S
1315     {
1316         int* ptr;
1317     }
1318     static assert(!isPointer!S);
1319 
1320     // The struct itself isn't considered a numeric type,
1321     // but its member variable is when checked directly.
1322     static assert( isPointer!(typeof(S.ptr)));
1323 
1324     enum E : immutable(char*)
1325     {
1326         a = "foobar".ptr
1327     }
1328 
1329     // Enums do not count.
1330     static assert(!isPointer!E);
1331 
1332     static struct AliasThis
1333     {
1334         int* ptr;
1335         alias this = ptr;
1336     }
1337 
1338     // Other implicit conversions do not count.
1339     static assert(!isPointer!AliasThis);
1340 }
1341 
1342 @safe unittest
1343 {
1344     import phobos.sys.meta : Alias, AliasSeq;
1345 
1346     static struct AliasThis(T)
1347     {
1348         T member;
1349         alias this = member;
1350     }
1351 
1352     static struct S
1353     {
1354         int i;
1355     }
1356 
1357     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
1358     {
1359         foreach (T; AliasSeq!(long*, S*, S**, S***, double[]*))
1360         {
1361             enum E : Q!T { a = Q!T.init }
1362 
1363             static assert( isPointer!(Q!T));
1364             static assert(!isPointer!E);
1365             static assert(!isPointer!(AliasThis!(Q!T)));
1366         }
1367 
1368         foreach (T; AliasSeq!(bool, char, wchar, dchar, byte, int, uint, long,
1369                               int[], float[8], real[], void[]))
1370         {
1371             enum E : Q!T { a = Q!T.init }
1372 
1373             static assert(!isPointer!(Q!T));
1374             static assert(!isPointer!E);
1375             static assert(!isPointer!(AliasThis!(Q!T)));
1376         }
1377     }
1378 }
1379 
1380 /++
1381     Evaluates to $(D true) if given a type and $(D false) for all other symbols.
1382 
1383     This is equivalent to $(D is(T)), but some people may find using a named
1384     trait to be clearer, and it can be used in conjunction with templates that
1385     take a template predicate (such as those in phobos.sys.meta), which can't
1386     be done with naked is expressions.
1387 
1388     See_Also:
1389         $(DDSUBLINK dlang.org/spec/expression.html, is-type, Spec on the related is expression)
1390   +/
1391 enum isType(T) = true;
1392 
1393 /// Ditto
1394 enum isType(alias sym) = false;
1395 
1396 ///
1397 @safe unittest
1398 {
1399     static assert( isType!int);
1400     static assert( isType!(int[]));
1401     static assert( isType!string);
1402     static assert( isType!(int[int]));
1403     static assert( isType!(ubyte*));
1404     static assert( isType!void);
1405 
1406     int i;
1407     static assert(!isType!i);
1408     static assert( isType!(typeof(i)));
1409 
1410     struct S {}
1411     static assert( isType!S);
1412     static assert(!isType!(S.init));
1413 
1414     class C {}
1415     static assert( isType!C);
1416     static assert(!isType!(C.init));
1417 
1418     interface I {}
1419     static assert( isType!I);
1420     static assert(!isType!(I.init));
1421 
1422     union U {}
1423     static assert( isType!U);
1424     static assert(!isType!(U.init));
1425 
1426     static void func() {}
1427     static assert(!isType!func);
1428     static assert( isType!(typeof(func)));
1429 
1430     void funcWithContext() { ++i; }
1431     static assert(!isType!funcWithContext);
1432     static assert( isType!(typeof(funcWithContext)));
1433 
1434     int function() funcPtr;
1435     static assert(!isType!funcPtr);
1436     static assert( isType!(typeof(funcPtr)));
1437 
1438     int delegate() del;
1439     static assert(!isType!del);
1440     static assert( isType!(typeof(del)));
1441 
1442     template Templ() {}
1443     static assert(!isType!Templ);
1444     static assert(!isType!(Templ!()));
1445 
1446     template TemplWithType()
1447     {
1448         struct S {}
1449     }
1450     static assert(!isType!TemplWithType);
1451     static assert(!isType!(TemplWithType!()));
1452     static assert( isType!(TemplWithType!().S));
1453 
1454     struct TemplType() {}
1455     static assert(!isType!TemplType);
1456     static assert( isType!(TemplType!()));
1457 }
1458 
1459 /++
1460     Evaluates to $(D true) if the given type or symbol is an instantiation of
1461     the given template.
1462 
1463     The overload which takes $(D T) operates on types and indicates whether an
1464     aggregate type (i.e. struct, class, interface, or union) is an
1465     instantiation of the given template.
1466 
1467     The overload which takes $(D Symbol) operates on function templates,
1468     because unlike with aggregate types, the type of a function does not retain
1469     the fact that it was instantiated from a template. So, for functions, it's
1470     necessary to pass the function itself as a symbol rather than pass the type
1471     of the function.
1472 
1473     The overload which takes $(D Symbol) also works with templates which are
1474     not types or functions.
1475 
1476     The single-argument overload makes it so that it can be partially
1477     instantiated with the first argument, which will often be necessary with
1478     template predicates.
1479   +/
1480 template isInstantiationOf(alias Template, T)
1481 if (__traits(isTemplate, Template))
1482 {
1483     enum isInstantiationOf = is(T == Template!Args, Args...);
1484 }
1485 
1486 /++ Ditto +/
1487 template isInstantiationOf(alias Template, alias Symbol)
1488 if (__traits(isTemplate, Template))
1489 {
1490     enum impl(alias T : Template!Args, Args...) = true;
1491     enum impl(alias T) = false;
1492     enum isInstantiationOf = impl!Symbol;
1493 }
1494 
1495 /++ Ditto +/
1496 template isInstantiationOf(alias Template)
1497 if (__traits(isTemplate, Template))
1498 {
1499     enum isInstantiationOf(T) = is(T == Template!Args, Args...);
1500 
1501     template isInstantiationOf(alias Symbol)
1502     {
1503         enum impl(alias T : Template!Args, Args...) = true;
1504         enum impl(alias T) = false;
1505         enum isInstantiationOf = impl!Symbol;
1506     }
1507 }
1508 
1509 /// Examples of templated types.
1510 @safe unittest
1511 {
1512     static struct S(T) {}
1513     static class C(T) {}
1514 
1515     static assert( isInstantiationOf!(S, S!int));
1516     static assert( isInstantiationOf!(S, S!int));
1517     static assert( isInstantiationOf!(S, S!string));
1518     static assert( isInstantiationOf!(S, const S!string));
1519     static assert( isInstantiationOf!(S, shared S!string));
1520     static assert(!isInstantiationOf!(S, int));
1521     static assert(!isInstantiationOf!(S, C!int));
1522     static assert(!isInstantiationOf!(S, C!string));
1523     static assert(!isInstantiationOf!(S, C!(S!int)));
1524 
1525     static assert( isInstantiationOf!(C, C!int));
1526     static assert( isInstantiationOf!(C, C!string));
1527     static assert( isInstantiationOf!(C, const C!string));
1528     static assert( isInstantiationOf!(C, shared C!string));
1529     static assert(!isInstantiationOf!(C, int));
1530     static assert(!isInstantiationOf!(C, S!int));
1531     static assert(!isInstantiationOf!(C, S!string));
1532     static assert(!isInstantiationOf!(C, S!(C!int)));
1533 
1534     static struct Variadic(T...) {}
1535 
1536     static assert( isInstantiationOf!(Variadic, Variadic!()));
1537     static assert( isInstantiationOf!(Variadic, Variadic!int));
1538     static assert( isInstantiationOf!(Variadic, Variadic!(int, string)));
1539     static assert( isInstantiationOf!(Variadic, Variadic!(int, string, int)));
1540     static assert( isInstantiationOf!(Variadic, const Variadic!(int, short)));
1541     static assert( isInstantiationOf!(Variadic, shared Variadic!(int, short)));
1542     static assert(!isInstantiationOf!(Variadic, int));
1543     static assert(!isInstantiationOf!(Variadic, S!int));
1544     static assert(!isInstantiationOf!(Variadic, C!int));
1545 
1546     static struct ValueArg(int i) {}
1547     static assert( isInstantiationOf!(ValueArg, ValueArg!42));
1548     static assert( isInstantiationOf!(ValueArg, ValueArg!256));
1549     static assert( isInstantiationOf!(ValueArg, const ValueArg!1024));
1550     static assert( isInstantiationOf!(ValueArg, shared ValueArg!1024));
1551     static assert(!isInstantiationOf!(ValueArg, int));
1552     static assert(!isInstantiationOf!(ValueArg, S!int));
1553 
1554     int i;
1555 
1556     static struct AliasArg(alias Symbol) {}
1557     static assert( isInstantiationOf!(AliasArg, AliasArg!42));
1558     static assert( isInstantiationOf!(AliasArg, AliasArg!int));
1559     static assert( isInstantiationOf!(AliasArg, AliasArg!i));
1560     static assert( isInstantiationOf!(AliasArg, const AliasArg!i));
1561     static assert( isInstantiationOf!(AliasArg, shared AliasArg!i));
1562     static assert(!isInstantiationOf!(AliasArg, int));
1563     static assert(!isInstantiationOf!(AliasArg, S!int));
1564 
1565     // An uninstantiated template is not an instance of any template,
1566     // not even itself.
1567     static assert(!isInstantiationOf!(S, S));
1568     static assert(!isInstantiationOf!(S, C));
1569     static assert(!isInstantiationOf!(C, C));
1570     static assert(!isInstantiationOf!(C, S));
1571 
1572     // Variables of a templated type are not considered instantiations of that
1573     // type. For templated types, the overload which takes a type must be used.
1574     S!int s;
1575     C!string c;
1576     static assert(!isInstantiationOf!(S, s));
1577     static assert(!isInstantiationOf!(C, c));
1578 }
1579 
1580 // Examples of templated functions.
1581 @safe unittest
1582 {
1583     static int foo(T...)() { return 42; }
1584     static void bar(T...)(T var) {}
1585     static void baz(T)(T var) {}
1586     static bool frobozz(alias pred)(int) { return true; }
1587 
1588     static assert( isInstantiationOf!(foo, foo!int));
1589     static assert( isInstantiationOf!(foo, foo!string));
1590     static assert( isInstantiationOf!(foo, foo!(int, string)));
1591     static assert(!isInstantiationOf!(foo, bar!int));
1592     static assert(!isInstantiationOf!(foo, bar!string));
1593     static assert(!isInstantiationOf!(foo, bar!(int, string)));
1594 
1595     static assert( isInstantiationOf!(bar, bar!int));
1596     static assert( isInstantiationOf!(bar, bar!string));
1597     static assert( isInstantiationOf!(bar, bar!(int, string)));
1598     static assert(!isInstantiationOf!(bar, foo!int));
1599     static assert(!isInstantiationOf!(bar, foo!string));
1600     static assert(!isInstantiationOf!(bar, foo!(int, string)));
1601 
1602     static assert( isInstantiationOf!(baz, baz!int));
1603     static assert( isInstantiationOf!(baz, baz!string));
1604     static assert(!isInstantiationOf!(baz, foo!(int, string)));
1605 
1606     static assert( isInstantiationOf!(frobozz, frobozz!(a => a)));
1607     static assert( isInstantiationOf!(frobozz, frobozz!(a => a > 2)));
1608     static assert(!isInstantiationOf!(frobozz, baz!int));
1609 
1610     // Unfortunately, the function type is not considered an instantiation of
1611     // the template, because that information is not part of the type, unlike
1612     // with templated structs or classes.
1613     static assert(!isInstantiationOf!(foo, typeof(foo!int)));
1614     static assert(!isInstantiationOf!(bar, typeof(bar!int)));
1615 }
1616 
1617 // Examples of templates which aren't types or functions.
1618 @safe unittest
1619 {
1620     template SingleArg(T) {}
1621     template Variadic(T...) {}
1622     template ValueArg(string s) {}
1623     template Alias(alias symbol) {}
1624 
1625     static assert( isInstantiationOf!(SingleArg, SingleArg!int));
1626     static assert( isInstantiationOf!(SingleArg, SingleArg!string));
1627     static assert(!isInstantiationOf!(SingleArg, int));
1628     static assert(!isInstantiationOf!(SingleArg, Variadic!int));
1629 
1630     static assert( isInstantiationOf!(Variadic, Variadic!()));
1631     static assert( isInstantiationOf!(Variadic, Variadic!int));
1632     static assert( isInstantiationOf!(Variadic, Variadic!string));
1633     static assert( isInstantiationOf!(Variadic, Variadic!(short, int, long)));
1634     static assert(!isInstantiationOf!(Variadic, int));
1635     static assert(!isInstantiationOf!(Variadic, SingleArg!int));
1636 
1637     static assert( isInstantiationOf!(ValueArg, ValueArg!"dlang"));
1638     static assert( isInstantiationOf!(ValueArg, ValueArg!"foobar"));
1639     static assert(!isInstantiationOf!(ValueArg, string));
1640     static assert(!isInstantiationOf!(ValueArg, Variadic!string));
1641 
1642     int i;
1643 
1644     static assert( isInstantiationOf!(Alias, Alias!int));
1645     static assert( isInstantiationOf!(Alias, Alias!42));
1646     static assert( isInstantiationOf!(Alias, Alias!i));
1647     static assert(!isInstantiationOf!(Alias, int));
1648     static assert(!isInstantiationOf!(Alias, SingleArg!int));
1649 }
1650 
1651 /// Examples of partial instantation.
1652 @safe unittest
1653 {
1654     static struct SingleArg(T) {}
1655     static struct Variadic(T...) {}
1656 
1657     alias isSingleArg = isInstantiationOf!SingleArg;
1658     alias isVariadic = isInstantiationOf!Variadic;
1659 
1660     static assert( isSingleArg!(SingleArg!int));
1661     static assert( isSingleArg!(const SingleArg!int));
1662     static assert(!isSingleArg!int);
1663     static assert(!isSingleArg!(Variadic!int));
1664 
1665     static assert( isVariadic!(Variadic!()));
1666     static assert( isVariadic!(Variadic!int));
1667     static assert( isVariadic!(shared Variadic!int));
1668     static assert( isVariadic!(Variadic!(int, string)));
1669     static assert(!isVariadic!int);
1670     static assert(!isVariadic!(SingleArg!int));
1671 
1672     T foo(T)(T t) { return t; }
1673     T likeFoo(T)(T t) { return t; }
1674     bool bar(alias pred)(int i) { return pred(i); }
1675 
1676     alias isFoo = isInstantiationOf!foo;
1677     alias isBar = isInstantiationOf!bar;
1678 
1679     static assert( isFoo!(foo!int));
1680     static assert( isFoo!(foo!string));
1681     static assert(!isFoo!int);
1682     static assert(!isFoo!(likeFoo!int));
1683     static assert(!isFoo!(bar!(a => true)));
1684 
1685     static assert( isBar!(bar!(a => true)));
1686     static assert( isBar!(bar!(a => a > 2)));
1687     static assert(!isBar!int);
1688     static assert(!isBar!(foo!int));
1689     static assert(!isBar!(likeFoo!int));
1690 }
1691 
1692 /++
1693     Evaluates to the default-initialized value of the given type.
1694 
1695     defaultInit should be used in generic code in contexts where the
1696     default-initialized value of a type is needed rather than that type's
1697     $(D init) value.
1698 
1699     For most types, the default-initialized value of a type $(I is) its
1700     $(D init) value - i.e. for some type, $(D T), it would normally be
1701     $(D T.init). However, there are some corner cases in the language where a
1702     type's $(D init) value is not its default-initialized value. In particular,
1703 
1704     1. If a type is a non-$(K_STATIC) nested struct, it has a context pointer
1705        which refers to the scope in which it's declared. So, its
1706        default-initialized value is its $(D init) value $(I plus) the value for
1707        its context pointer. However, if such a nested struct is explicitly
1708        initialized with just its $(D init) value instead of being
1709        default-initialized or being constructed via a constructor, then its
1710        context pointer is $(K_NULL), potentially leading to segfaults when the
1711        object is used.
1712     2. If a type is a struct for which default initialization has been disabled
1713        using $(D @disable this();), then while its $(D init) value is still used
1714        as the value of the object at the start of a constructor call (as is the
1715        case with any struct), the struct cannot be default-initialized and must
1716        instead be explicitly constructed. So, instead of $(D T.init) being the
1717        default-initialized value, it's just the struct's initial state before
1718        the constructor constructs the object, and the struct does not actually
1719        have a default-initialized value.
1720 
1721     In the case of #2, there is no default initialization for the struct,
1722     whereas in the case of #1, there $(I is) default initialization for the
1723     struct but only within the scope where the struct is declared. Outside of
1724     that scope, the compiler does not have access to that scope and therefore
1725     cannot iniitialize the context pointer with a value, so a compilation error
1726     results. And so, either case can make it so that a struct cannot be
1727     default-initialized.
1728 
1729     In both cases, an instance of the struct can still be explicitly
1730     initialized with its $(D init) value, but that will usually lead to
1731     incorrect code, because either the object's context pointer will be
1732     $(K_NULL), or it's a type which was designed with the idea that it would
1733     only ever be explicitly constructed. So, while sometimes it's still
1734     appropriate to explicitly use the $(D init) value (e.g. by default,
1735     $(REF1 destroy, object) will set the object to its $(D init) value after
1736     destroying it so that it's in a valid state to have its destructor called
1737     afterwards in cases where the object is still going to be destroyed when it
1738     leaves scope), in general, generic code which needs to explicitly
1739     default-initialize a variable shouldn't use the type's $(D init) value.
1740 
1741     For a type, $(D T), which is a struct which does not declare a $(K_STATIC)
1742     $(D opCall), $(D T()) can be used instead of $(D T.init) to get the type's
1743     default-initialized value, and unlike $(D T.init), it will fail to compile
1744     if the object cannot actually be default-initialized (be it because it has
1745     disabled default initialization, or because it's a nested struct outside of
1746     the scope where that struct was declared). So, unlike $(D T.init), it
1747     won't compile in cases where default initialization does not work, and thus
1748     it can't accidentally be used to initialize a struct which cannot be
1749     default-intiialized. Also, for nested structs, $(D T()) will initialize the
1750     context pointer, unlike $(D T.init). So, using $(D T()) normally gives the
1751     actual default-initialized value for the type or fails to compile if the
1752     type cannot be default-initialized.
1753 
1754     However, unfortunately, using $(D T()) does not work in generic code,
1755     because it is legal for a struct to declare a $(K_STATIC) $(D opCall) which
1756     takes no arguments, overriding the normal behavior of $(D T()) and making
1757     it so that it's no longer the default-initialized value. Instead, it's
1758     whatever $(K_STATIC) $(D opCall) returns, and $(K_STATIC) $(D opCall) can
1759     return any type, not just $(D T), because even though it looks like a
1760     constructor call, it's not actually a constructor call, and it can return
1761     whatever the programmer felt like - including $(K_VOID). This means that
1762     the only way to consistently get a default-initialized value for a type in
1763     generic code is to actually declare a variable and not give it a value.
1764 
1765     So, in order to work around that, defaultInit does that for you.
1766     $(D defaultInit!Foo) evaluates to the default-initialized value of $(D Foo),
1767     but unlike $(D Foo.init), it won't compile when $(D Foo) cannot be
1768     default-initialized. And it won't get hijacked by $(K_STATIC) $(D opCall).
1769 
1770     The downside to using such a helper template is that it will not work with
1771     a nested struct even within the scope where that nested struct is declared
1772     (since defaultInit is declared outside of that scope). So, code which needs
1773     to get a default-initialized instance of a nested struct within the scope
1774     where it's declared will either have to simply declare a variable and not
1775     initialize it or use $(D T()) to explicitly get the default-initialized
1776     value. And since this is within the code where the type is declared, it's
1777     fully within the programmer's control to not declare a $(K_STATIC)
1778     $(D opCall) for it. So, it shouldn't be a problem in practice.
1779   +/
1780 template defaultInit(T)
1781 if (is(typeof({T t;})))
1782 {
1783     // At present, simply using T.init should work, since all of the cases where
1784     // it wouldn't won't get past the template constraint. However, it's
1785     // possible that that will change at some point in the future, and this
1786     // approach is guaranteed to give whatever the default-initialized value is
1787     // regardless of whether it's T.init.
1788     enum defaultInit = (){ T retval; return retval; }();
1789 }
1790 
1791 ///
1792 @safe unittest
1793 {
1794     static assert(defaultInit!int == 0);
1795     static assert(defaultInit!bool == false);
1796     static assert(defaultInit!(int*) is null);
1797     static assert(defaultInit!(int[]) is null);
1798     static assert(defaultInit!string is null);
1799     static assert(defaultInit!(int[2]) == [0, 0]);
1800 
1801     static struct S
1802     {
1803         int i = 42;
1804     }
1805     static assert(defaultInit!S == S(42));
1806 
1807     static assert(defaultInit!Object is null);
1808 
1809     interface I
1810     {
1811         bool foo();
1812     }
1813     static assert(defaultInit!I is null);
1814 
1815     static struct NoDefaultInit
1816     {
1817         int i;
1818         @disable this();
1819     }
1820 
1821     // It's not legal to default-initialize NoDefaultInit, because it has
1822     // disabled default initialization.
1823     static assert(!__traits(compiles, defaultInit!NoDefaultInit));
1824 
1825     int var = 2;
1826     struct Nested
1827     {
1828         int i = 40;
1829 
1830         int foo()
1831         {
1832             return i + var;
1833         }
1834     }
1835 
1836     // defaultInit doesn't have access to this scope and thus cannot
1837     // initialize the nested struct.
1838     static assert(!__traits(compiles, defaultInit!Nested));
1839 
1840     // However, because Nested has no static opCall (and we know it doesn't
1841     // because we're doing this in the same scope where Nested was declared),
1842     // Nested() can be used to get the default-initialized value.
1843     static assert(Nested() == Nested(40));
1844 
1845     Nested nested;
1846     assert(Nested() == nested);
1847 
1848     // Both have properly initialized context pointers,
1849     // whereas Nested.init does not.
1850     assert(Nested().foo() == nested.foo());
1851 
1852     // defaultInit does not get hijacked by static opCall.
1853     static struct HasOpCall
1854     {
1855         int i;
1856 
1857         static opCall()
1858         {
1859             return HasOpCall(42);
1860         }
1861 
1862         static opCall(int i)
1863         {
1864             HasOpCall retval;
1865             retval.i = i;
1866             return retval;
1867         }
1868     }
1869 
1870     static assert(defaultInit!HasOpCall == HasOpCall(0));
1871     static assert(HasOpCall() == HasOpCall(42));
1872 }
1873 
1874 @safe unittest
1875 {
1876     static struct NoCopy
1877     {
1878         int i = 17;
1879         @disable this(this);
1880     }
1881     static assert(defaultInit!NoCopy == NoCopy(17));
1882 
1883     string function() funcPtr;
1884     static assert(defaultInit!(SymbolType!funcPtr) is null);
1885 
1886     string delegate() del;
1887     static assert(defaultInit!(SymbolType!del) is null);
1888 
1889     int function() @property propFuncPtr;
1890     static assert(defaultInit!(SymbolType!propFuncPtr) is null);
1891 
1892     int delegate() @property propDel;
1893     static assert(defaultInit!(SymbolType!propDel) is null);
1894 }
1895 
1896 /++
1897     Evaluates to an $(D AliasSeq) containing the members of an enum type.
1898 
1899     The elements of the $(D AliasSeq) are in the same order as they are in the
1900     enum declaration.
1901 
1902     An enum can have multiple members with the same value, so if code needs the
1903     enum values to be unique (e.g. if it's generating a switch statement from
1904     them), then $(REF Unique, phobos, sys, meta) can be used to filter out the
1905     duplicate values - e.g. $(D Unique!(isEqual, EnumMembers!E)).
1906   +/
1907 template EnumMembers(E)
1908 if (is(E == enum))
1909 {
1910     import phobos.sys.meta : AliasSeq;
1911 
1912     alias EnumMembers = AliasSeq!();
1913     static foreach (member; __traits(allMembers, E))
1914         EnumMembers = AliasSeq!(EnumMembers, __traits(getMember, E, member));
1915 }
1916 
1917 /// Create an array of enum values.
1918 @safe unittest
1919 {
1920     enum Sqrts : real
1921     {
1922         one = 1,
1923         two = 1.41421,
1924         three = 1.73205
1925     }
1926     auto sqrts = [EnumMembers!Sqrts];
1927     assert(sqrts == [Sqrts.one, Sqrts.two, Sqrts.three]);
1928 }
1929 
1930 /++
1931     A generic function $(D rank(v)) in the following example uses this template
1932     for finding a member $(D e) in an enum type $(D E).
1933  +/
1934 @safe unittest
1935 {
1936     // Returns i if e is the i-th member of E.
1937     static size_t rank(E)(E e)
1938     if (is(E == enum))
1939     {
1940         static foreach (i, member; EnumMembers!E)
1941         {
1942             if (e == member)
1943                 return i;
1944         }
1945         assert(0, "Not an enum member");
1946     }
1947 
1948     enum Mode
1949     {
1950         read = 1,
1951         write = 2,
1952         map = 4
1953     }
1954     assert(rank(Mode.read) == 0);
1955     assert(rank(Mode.write) == 1);
1956     assert(rank(Mode.map) == 2);
1957 }
1958 
1959 /// Use EnumMembers to generate a switch statement using static foreach.
1960 @safe unittest
1961 {
1962     static class Foo
1963     {
1964         string calledMethod;
1965         void foo() @safe { calledMethod = "foo"; }
1966         void bar() @safe { calledMethod = "bar"; }
1967         void baz() @safe { calledMethod = "baz"; }
1968     }
1969 
1970     enum FuncName : string { foo = "foo", bar = "bar", baz = "baz" }
1971 
1972     auto foo = new Foo;
1973 
1974     s: final switch (FuncName.bar)
1975     {
1976         static foreach (member; EnumMembers!FuncName)
1977         {
1978             // Generate a case for each enum value.
1979             case member:
1980             {
1981                 // Call foo.{enum value}().
1982                 __traits(getMember, foo, member)();
1983                 break s;
1984             }
1985         }
1986     }
1987 
1988     // Since we passed FuncName.bar to the switch statement, the bar member
1989     // function was called.
1990     assert(foo.calledMethod == "bar");
1991 }
1992 
1993 @safe unittest
1994 {
1995     {
1996         enum A { a }
1997         static assert([EnumMembers!A] == [A.a]);
1998         enum B { a, b, c, d, e }
1999         static assert([EnumMembers!B] == [B.a, B.b, B.c, B.d, B.e]);
2000     }
2001     {
2002         enum A : string { a = "alpha", b = "beta" }
2003         static assert([EnumMembers!A] == [A.a, A.b]);
2004 
2005         static struct S
2006         {
2007             int value;
2008             int opCmp(S rhs) const nothrow { return value - rhs.value; }
2009         }
2010         enum B : S { a = S(1), b = S(2), c = S(3) }
2011         static assert([EnumMembers!B] == [B.a, B.b, B.c]);
2012     }
2013     {
2014         enum A { a = 0, b = 0, c = 1, d = 1, e }
2015         static assert([EnumMembers!A] == [A.a, A.b, A.c, A.d, A.e]);
2016     }
2017     {
2018         enum E { member, a = 0, b = 0 }
2019 
2020         static assert(__traits(isSame, EnumMembers!E[0], E.member));
2021         static assert(__traits(isSame, EnumMembers!E[1], E.a));
2022         static assert(__traits(isSame, EnumMembers!E[2], E.b));
2023 
2024         static assert(__traits(identifier, EnumMembers!E[0]) == "member");
2025         static assert(__traits(identifier, EnumMembers!E[1]) == "a");
2026         static assert(__traits(identifier, EnumMembers!E[2]) == "b");
2027     }
2028 }
2029 
2030 // https://issues.dlang.org/show_bug.cgi?id=14561: huge enums
2031 @safe unittest
2032 {
2033     static string genEnum()
2034     {
2035         string result = "enum TLAs {";
2036         foreach (c0; '0' .. '2' + 1)
2037         {
2038             foreach (c1; '0' .. '9' + 1)
2039             {
2040                 foreach (c2; '0' .. '9' + 1)
2041                 {
2042                     foreach (c3; '0' .. '9' + 1)
2043                     {
2044                         result ~= '_';
2045                         result ~= c0;
2046                         result ~= c1;
2047                         result ~= c2;
2048                         result ~= c3;
2049                         result ~= ',';
2050                     }
2051                 }
2052             }
2053         }
2054         result ~= '}';
2055         return result;
2056     }
2057     mixin(genEnum);
2058     static assert(EnumMembers!TLAs[0] == TLAs._0000);
2059     static assert(EnumMembers!TLAs[$ - 1] == TLAs._2999);
2060 }
2061 
2062 /++
2063     Whether the type $(D From) is implicitly convertible to the type $(D To).
2064 
2065     Note that template constraints should be very careful about when they test
2066     for implicit conversions and in general should prefer to either test for an
2067     exact set of types or for types which compile with a particular piece of
2068     code rather than being designed to accept any type which implicitly converts
2069     to a particular type.
2070 
2071     This is because having a type pass a template constraint based on an
2072     implicit conversion but then not have the implicit conversion actually take
2073     place (which it won't unless the template does something to force it
2074     internally) can lead to either compilation errors or subtle behavioral
2075     differences - and even when the conversion is done explicitly within a
2076     templated function, since it's not done at the call site, it can still lead
2077     to subtle bugs in some cases (e.g. if slicing a static array is involved).
2078 
2079     For situations where code needs to verify that a type is implicitly
2080     convertible based solely on its qualifiers, $(LREF isQualifierConvertible)
2081     would be a more appropriate choice than isImplicitlyConvertible.
2082 
2083     Given how trivial the $(D is) expression for isImplicitlyConvertible is -
2084     $(D is(To : From)) - this trait is provided primarily so that it can be
2085     used in conjunction with templates that use a template predicate (such as
2086     many of the templates in phobos.sys.meta).
2087 
2088     The single-argument overload makes it so that it can be partially
2089     instantiated with the first argument, which will often be necessary with
2090     template predicates.
2091 
2092     See_Also:
2093         $(DDSUBLINK dlang.org/spec/type, implicit-conversions, Spec on implicit conversions)
2094         $(DDSUBLINK spec/const3, implicit_qualifier_conversions, Spec for implicit qualifier conversions)
2095         $(LREF isQualifierConvertible)
2096   +/
2097 enum isImplicitlyConvertible(From, To) = is(From : To);
2098 
2099 /++ Ditto +/
2100 template isImplicitlyConvertible(From)
2101 {
2102     enum isImplicitlyConvertible(To) = is(From : To);
2103 }
2104 
2105 ///
2106 @safe unittest
2107 {
2108     static assert( isImplicitlyConvertible!(byte, long));
2109     static assert( isImplicitlyConvertible!(ushort, long));
2110     static assert( isImplicitlyConvertible!(int, long));
2111     static assert( isImplicitlyConvertible!(long, long));
2112     static assert( isImplicitlyConvertible!(ulong, long));
2113 
2114     static assert( isImplicitlyConvertible!(ubyte, int));
2115     static assert( isImplicitlyConvertible!(short, int));
2116     static assert( isImplicitlyConvertible!(int, int));
2117     static assert( isImplicitlyConvertible!(uint, int));
2118     static assert(!isImplicitlyConvertible!(long, int));
2119     static assert(!isImplicitlyConvertible!(ulong, int));
2120 
2121     static assert(!isImplicitlyConvertible!(int, string));
2122     static assert(!isImplicitlyConvertible!(int, int[]));
2123     static assert(!isImplicitlyConvertible!(int, int*));
2124 
2125     static assert(!isImplicitlyConvertible!(string, int));
2126     static assert(!isImplicitlyConvertible!(int[], int));
2127     static assert(!isImplicitlyConvertible!(int*, int));
2128 
2129     // For better or worse, bool and the built-in character types will
2130     // implicitly convert to integer or floating-point types if the target type
2131     // is large enough. Sometimes, this is desirable, whereas at other times,
2132     // it can have very surprising results, so it's one reason why code should
2133     // be very careful when testing for implicit conversions.
2134     static assert( isImplicitlyConvertible!(bool, int));
2135     static assert( isImplicitlyConvertible!(char, int));
2136     static assert( isImplicitlyConvertible!(wchar, int));
2137     static assert( isImplicitlyConvertible!(dchar, int));
2138 
2139     static assert( isImplicitlyConvertible!(bool, ubyte));
2140     static assert( isImplicitlyConvertible!(char, ubyte));
2141     static assert(!isImplicitlyConvertible!(wchar, ubyte));
2142     static assert(!isImplicitlyConvertible!(dchar, ubyte));
2143 
2144     static assert( isImplicitlyConvertible!(bool, double));
2145     static assert( isImplicitlyConvertible!(char, double));
2146     static assert( isImplicitlyConvertible!(wchar, double));
2147     static assert( isImplicitlyConvertible!(dchar, double));
2148 
2149     // Value types can be implicitly converted regardless of their qualifiers
2150     // thanks to the fact that they're copied.
2151     static assert( isImplicitlyConvertible!(int, int));
2152     static assert( isImplicitlyConvertible!(const int, int));
2153     static assert( isImplicitlyConvertible!(immutable int, int));
2154     static assert( isImplicitlyConvertible!(inout int, int));
2155 
2156     static assert( isImplicitlyConvertible!(int, const int));
2157     static assert( isImplicitlyConvertible!(int, immutable int));
2158     static assert( isImplicitlyConvertible!(int, inout int));
2159 
2160     // Reference types are far more restrictive about which implicit conversions
2161     // they allow, because qualifiers in D are transitive.
2162     static assert( isImplicitlyConvertible!(int*, int*));
2163     static assert(!isImplicitlyConvertible!(const int*, int*));
2164     static assert(!isImplicitlyConvertible!(immutable int*, int*));
2165 
2166     static assert( isImplicitlyConvertible!(int*, const int*));
2167     static assert( isImplicitlyConvertible!(const int*, const int*));
2168     static assert( isImplicitlyConvertible!(immutable int*, const int*));
2169 
2170     static assert(!isImplicitlyConvertible!(int*, immutable int*));
2171     static assert(!isImplicitlyConvertible!(const int*, immutable int*));
2172     static assert( isImplicitlyConvertible!(immutable int*, immutable int*));
2173 
2174     // Note that inout gets a bit weird, since it's only used with function
2175     // parameters, and it's a stand-in for whatever mutability qualifiers the
2176     // type actually has. So, a function parameter that's inout accepts any
2177     // mutability, but you can't actually implicitly convert to inout, because
2178     // it's unknown within the function what the actual mutability of the type
2179     // is. It will differ depending on the function arguments of a specific
2180     // call to that function, so the same code has to work with all combinations
2181     // of mutability qualifiers.
2182     static assert(!isImplicitlyConvertible!(int*, inout int*));
2183     static assert(!isImplicitlyConvertible!(const int*, inout int*));
2184     static assert(!isImplicitlyConvertible!(immutable int*, inout int*));
2185     static assert( isImplicitlyConvertible!(inout int*, inout int*));
2186 
2187     static assert(!isImplicitlyConvertible!(inout int*, int*));
2188     static assert( isImplicitlyConvertible!(inout int*, const int*));
2189     static assert(!isImplicitlyConvertible!(inout int*, immutable int*));
2190 
2191     // Enums implicitly convert to their base type.
2192     enum E : int
2193     {
2194         a = 42
2195     }
2196     static assert( isImplicitlyConvertible!(E, int));
2197     static assert( isImplicitlyConvertible!(E, long));
2198     static assert(!isImplicitlyConvertible!(E, int[]));
2199 
2200     // Structs only implicit convert to another type via declaring an
2201     // alias this.
2202     static struct S
2203     {
2204         int i;
2205     }
2206     static assert(!isImplicitlyConvertible!(S, int));
2207     static assert(!isImplicitlyConvertible!(S, long));
2208     static assert(!isImplicitlyConvertible!(S, string));
2209 
2210     static struct AliasThis
2211     {
2212         int i;
2213         alias this = i;
2214     }
2215     static assert( isImplicitlyConvertible!(AliasThis, int));
2216     static assert( isImplicitlyConvertible!(AliasThis, long));
2217     static assert(!isImplicitlyConvertible!(AliasThis, string));
2218 
2219     static struct AliasThis2
2220     {
2221         AliasThis at;
2222         alias this = at;
2223     }
2224     static assert( isImplicitlyConvertible!(AliasThis2, AliasThis));
2225     static assert( isImplicitlyConvertible!(AliasThis2, int));
2226     static assert( isImplicitlyConvertible!(AliasThis2, long));
2227     static assert(!isImplicitlyConvertible!(AliasThis2, string));
2228 
2229     static struct AliasThis3
2230     {
2231         AliasThis2 at;
2232         alias this = at;
2233     }
2234     static assert( isImplicitlyConvertible!(AliasThis3, AliasThis2));
2235     static assert( isImplicitlyConvertible!(AliasThis3, AliasThis));
2236     static assert( isImplicitlyConvertible!(AliasThis3, int));
2237     static assert( isImplicitlyConvertible!(AliasThis3, long));
2238     static assert(!isImplicitlyConvertible!(AliasThis3, string));
2239 
2240     // D does not support implicit conversions via construction.
2241     static struct Cons
2242     {
2243         this(int i)
2244         {
2245             this.i = i;
2246         }
2247 
2248         int i;
2249     }
2250     static assert(!isImplicitlyConvertible!(int, Cons));
2251 
2252     // Classes support implicit conversion based on their class and
2253     // interface hierarchies.
2254     static interface I1 {}
2255     static class Base : I1 {}
2256 
2257     static interface I2 {}
2258     static class Foo : Base, I2 {}
2259 
2260     static class Bar : Base {}
2261 
2262     static assert( isImplicitlyConvertible!(Base, Base));
2263     static assert(!isImplicitlyConvertible!(Base, Foo));
2264     static assert(!isImplicitlyConvertible!(Base, Bar));
2265     static assert( isImplicitlyConvertible!(Base, I1));
2266     static assert(!isImplicitlyConvertible!(Base, I2));
2267 
2268     static assert( isImplicitlyConvertible!(Foo, Base));
2269     static assert( isImplicitlyConvertible!(Foo, Foo));
2270     static assert(!isImplicitlyConvertible!(Foo, Bar));
2271     static assert( isImplicitlyConvertible!(Foo, I1));
2272     static assert( isImplicitlyConvertible!(Foo, I2));
2273 
2274     static assert( isImplicitlyConvertible!(Bar, Base));
2275     static assert(!isImplicitlyConvertible!(Bar, Foo));
2276     static assert( isImplicitlyConvertible!(Bar, Bar));
2277     static assert( isImplicitlyConvertible!(Bar, I1));
2278     static assert(!isImplicitlyConvertible!(Bar, I2));
2279 
2280     static assert(!isImplicitlyConvertible!(I1, Base));
2281     static assert(!isImplicitlyConvertible!(I1, Foo));
2282     static assert(!isImplicitlyConvertible!(I1, Bar));
2283     static assert( isImplicitlyConvertible!(I1, I1));
2284     static assert(!isImplicitlyConvertible!(I1, I2));
2285 
2286     static assert(!isImplicitlyConvertible!(I2, Base));
2287     static assert(!isImplicitlyConvertible!(I2, Foo));
2288     static assert(!isImplicitlyConvertible!(I2, Bar));
2289     static assert(!isImplicitlyConvertible!(I2, I1));
2290     static assert( isImplicitlyConvertible!(I2, I2));
2291 
2292     // Note that arrays are not implicitly convertible even when their elements
2293     // are implicitly convertible.
2294     static assert(!isImplicitlyConvertible!(ubyte[], uint[]));
2295     static assert(!isImplicitlyConvertible!(Foo[], Base[]));
2296     static assert(!isImplicitlyConvertible!(Bar[], Base[]));
2297 
2298     // However, like with pointers, dynamic arrays are convertible based on
2299     // constness.
2300     static assert( isImplicitlyConvertible!(Base[], const Base[]));
2301     static assert( isImplicitlyConvertible!(Base[], const(Base)[]));
2302     static assert(!isImplicitlyConvertible!(Base[], immutable(Base)[]));
2303     static assert(!isImplicitlyConvertible!(const Base[], immutable Base[]));
2304     static assert( isImplicitlyConvertible!(const Base[], const Base[]));
2305     static assert(!isImplicitlyConvertible!(const Base[], immutable Base[]));
2306 }
2307 
2308 /++
2309     isImplicitlyConvertible can be used with partial instantiation so that it
2310     can be passed to a template which takes a unary predicate.
2311   +/
2312 @safe unittest
2313 {
2314     import phobos.sys.meta : AliasSeq, all, indexOf;
2315 
2316     // byte is implicitly convertible to byte, short, int, and long.
2317     static assert(all!(isImplicitlyConvertible!byte, short, int, long));
2318 
2319     // const(char)[] at index 2 is the first type in the AliasSeq which string
2320     // can be implicitly converted to.
2321     alias Types = AliasSeq!(int, char[], const(char)[], string, int*);
2322     static assert(indexOf!(isImplicitlyConvertible!string, Types) == 2);
2323 }
2324 
2325 /++
2326     Whether $(D From) is
2327     $(DDSUBLINK spec/const3, implicit_qualifier_conversions, qualifier-convertible)
2328     to $(D To).
2329 
2330     This is testing whether $(D From) and $(D To) are the same type - minus the
2331     qualifiers - and whether the qualifiers on $(D From) can be implicitly
2332     converted to the qualifiers on $(D To). No other implicit conversions are
2333     taken into account.
2334 
2335     For instance, $(D const int*) is not implicitly convertible to $(D int*),
2336     because that would violate $(D const). That means that $(D const) is not
2337     qualifier convertible to mutable. And as such, $(I any) $(D const) type
2338     is not qualifier convertible to a mutable type even if it's implicitly
2339     convertible. E.G. $(D const int) is implicitly convertible to $(D int),
2340     because it can be copied to avoid violating $(D const), but it's still not
2341     qualifier convertible, because $(D const) types in general cannot be
2342     implicitly converted to mutable.
2343 
2344     The exact types being tested matter, because they need to be the same
2345     (minus the qualifiers) in order to be considered convertible, but beyond
2346     that, all that matters for the conversion is whether those qualifers would
2347     be convertible regardless of which types they were on. So, if you're having
2348     trouble picturing whether $(D From) would be qualifier convertible to
2349     $(D To), then consider which conversions would be allowed from $(D From[])
2350     to $(D To[]) (and remember that dynamic arrays are only implicitly
2351     convertible based on their qualifers).
2352 
2353     The $(DDSUBLINK spec/const3, implicit_qualifier_conversions, spec) provides
2354     a table of which qualifiers can be implcitly converted to which other
2355     qualifers (and of course, there a bunch of examples below).
2356 
2357     So, isQualifierConvertible can be used in a case like
2358     $(D isQualifierConvertible!(ReturnType!(typeof(foo(bar))), const char),
2359     which would be testing that the return type of $(D foo(bar)) was $(D char),
2360     $(D const char), or $(D immutable char) (since those are the only types
2361     which are qualifier convertible to $(D const char)).
2362 
2363     This is in contrast to
2364     $(D isImplicitlyConvertible!(ReturnType!(typeof(foo(bar))), const char),
2365     which would be $(D true) for $(I any) type which was implicitly convertible
2366     to $(D const char) rather than just $(D char), $(D const char), and
2367     $(D immutable char).
2368 
2369     The single-argument overload makes it so that it can be partially
2370     instantiated with the first argument, which will often be necessary with
2371     template predicates.
2372 
2373     See_Also:
2374         $(DDSUBLINK spec/const3, implicit_qualifier_conversions, Spec for implicit qualifier conversions)
2375         $(LREF isImplicitlyConvertible)
2376   +/
2377 enum isQualifierConvertible(From, To) = is(immutable From == immutable To) && is(From* : To*);
2378 
2379 /++ Ditto +/
2380 template isQualifierConvertible(From)
2381 {
2382     enum isQualifierConvertible(To) =  is(immutable From == immutable To) && is(From* : To*);
2383 }
2384 
2385 ///
2386 @safe unittest
2387 {
2388     // i.e. char* -> const char*
2389     static assert( isQualifierConvertible!(char, const char));
2390 
2391     // i.e. const char* -> char*
2392     static assert(!isQualifierConvertible!(const char, char));
2393 
2394     static assert( isQualifierConvertible!(int, int));
2395     static assert( isQualifierConvertible!(int, const int));
2396     static assert(!isQualifierConvertible!(int, immutable int));
2397 
2398     static assert(!isQualifierConvertible!(const int, int));
2399     static assert( isQualifierConvertible!(const int, const int));
2400     static assert(!isQualifierConvertible!(const int, immutable int));
2401 
2402     static assert(!isQualifierConvertible!(immutable int, int));
2403     static assert( isQualifierConvertible!(immutable int, const int));
2404     static assert( isQualifierConvertible!(immutable int, immutable int));
2405 
2406     // Note that inout gets a bit weird, since it's only used with function
2407     // parameters, and it's a stand-in for whatever mutability qualifiers the
2408     // type actually has. So, a function parameter that's inout accepts any
2409     // mutability, but you can't actually implicitly convert to inout, because
2410     // it's unknown within the function what the actual mutability of the type
2411     // is. It will differ depending on the function arguments of a specific
2412     // call to that function, so the same code has to work with all combinations
2413     // of mutability qualifiers.
2414     static assert(!isQualifierConvertible!(int, inout int));
2415     static assert(!isQualifierConvertible!(const int, inout int));
2416     static assert(!isQualifierConvertible!(immutable int, inout int));
2417     static assert( isQualifierConvertible!(inout int, inout int));
2418 
2419     static assert(!isQualifierConvertible!(inout int, int));
2420     static assert( isQualifierConvertible!(inout int, const int));
2421     static assert(!isQualifierConvertible!(inout int, immutable int));
2422 
2423     // shared is of course also a qualifier.
2424     static assert(!isQualifierConvertible!(int, shared int));
2425     static assert(!isQualifierConvertible!(int, const shared int));
2426     static assert(!isQualifierConvertible!(const int, shared int));
2427     static assert(!isQualifierConvertible!(const int, const shared int));
2428     static assert(!isQualifierConvertible!(immutable int, shared int));
2429     static assert( isQualifierConvertible!(immutable int, const shared int));
2430 
2431     static assert(!isQualifierConvertible!(shared int, int));
2432     static assert(!isQualifierConvertible!(shared int, const int));
2433     static assert(!isQualifierConvertible!(shared int, immutable int));
2434     static assert( isQualifierConvertible!(shared int, shared int));
2435     static assert( isQualifierConvertible!(shared int, const shared int));
2436 
2437     static assert(!isQualifierConvertible!(const shared int, int));
2438     static assert(!isQualifierConvertible!(const shared int, const int));
2439     static assert(!isQualifierConvertible!(const shared int, immutable int));
2440     static assert(!isQualifierConvertible!(const shared int, shared int));
2441     static assert( isQualifierConvertible!(const shared int, const shared int));
2442 
2443     // Implicit conversions don't count unless they're based purely on
2444     // qualifiers.
2445     enum E : int
2446     {
2447         a = 1
2448     }
2449 
2450     static assert(!isQualifierConvertible!(E, int));
2451     static assert(!isQualifierConvertible!(E, const int));
2452     static assert( isQualifierConvertible!(E, E));
2453     static assert( isQualifierConvertible!(E, const E));
2454     static assert(!isQualifierConvertible!(E, immutable E));
2455 
2456     static struct AliasThis
2457     {
2458         int i;
2459         alias this = i;
2460     }
2461 
2462     static assert(!isQualifierConvertible!(AliasThis, int));
2463     static assert(!isQualifierConvertible!(AliasThis, const int));
2464     static assert( isQualifierConvertible!(AliasThis, AliasThis));
2465     static assert( isQualifierConvertible!(AliasThis, const AliasThis));
2466     static assert(!isQualifierConvertible!(AliasThis, immutable AliasThis));
2467 
2468     // The qualifiers are irrelevant if the types aren't the same when
2469     // stripped of all qualifers.
2470     static assert(!isQualifierConvertible!(int, long));
2471     static assert(!isQualifierConvertible!(int, const long));
2472     static assert(!isQualifierConvertible!(string, const(ubyte)[]));
2473 }
2474 
2475 /++
2476     isQualifierConvertible can be used with partial instantiation so that it
2477     can be passed to a template which takes a unary predicate.
2478   +/
2479 @safe unittest
2480 {
2481     import phobos.sys.meta : AliasSeq, all, indexOf;
2482 
2483     // byte is qualifier convertible to byte and const byte.
2484     static assert(all!(isQualifierConvertible!byte, byte, const byte));
2485 
2486     // const(char[]) at index 2 is the first type in the AliasSeq which string
2487     // is qualifier convertible to.
2488     alias Types = AliasSeq!(int, char[], const(char[]), string, int*);
2489     static assert(indexOf!(isQualifierConvertible!string, Types) == 2);
2490 }
2491 
2492 @safe unittest
2493 {
2494     import phobos.sys.meta : AliasSeq;
2495 
2496     alias Types = AliasSeq!(int, const int, shared int, inout int, const shared int,
2497                             const inout int, inout shared int, const inout shared int, immutable int);
2498 
2499     // https://dlang.org/spec/const3.html#implicit_qualifier_conversions
2500     enum _ = 0;
2501     static immutable bool[Types.length][Types.length] conversions = [
2502     //   m   c   s   i   cs  ci  is  cis im
2503         [1,  1,  _,  _,  _,  _,  _,  _,  _],  // mutable
2504         [_,  1,  _,  _,  _,  _,  _,  _,  _],  // const
2505         [_,  _,  1,  _,  1,  _,  _,  _,  _],  // shared
2506         [_,  1,  _,  1,  _,  1,  _,  _,  _],  // inout
2507         [_,  _,  _,  _,  1,  _,  _,  _,  _],  // const shared
2508         [_,  1,  _,  _,  _,  1,  _,  _,  _],  // const inout
2509         [_,  _,  _,  _,  1,  _,  1,  1,  _],  // inout shared
2510         [_,  _,  _,  _,  1,  _,  _,  1,  _],  // const inout shared
2511         [_,  1,  _,  _,  1,  1,  _,  1,  1],  // immutable
2512     ];
2513 
2514     foreach (i, From; Types)
2515     {
2516         foreach (j, To; Types)
2517         {
2518             static assert(isQualifierConvertible!(From, To) == conversions[i][j],
2519                           "`isQualifierConvertible!(" ~ From.stringof ~ ", " ~ To.stringof ~ ")`" ~
2520                           " should be `" ~ (conversions[i][j] ? "true`" : "false`"));
2521         }
2522     }
2523 }
2524 
2525 /++
2526     Whether the given values are equal per $(D ==).
2527 
2528     All this does is $(D lhs == rhs) but in an eponymous template, so most code
2529     shouldn't use it. It's intended to be used in conjunction with templates
2530     that take a template predicate - such as those in phobos.sys.meta.
2531 
2532     The single-argument overload makes it so that it can be partially
2533     instantiated with the first argument, which will often be necessary with
2534     template predicates.
2535 
2536     Note that in most cases, even when comparing values at compile time, using
2537     isEqual makes no sense, because you can use CTFE to just compare two values
2538     (or expressions which evaluate to values), but in rare cases where you need
2539     to compare symbols in an $(D AliasSeq) by value with a template predicate
2540     while still leaving them as symbols in an $(D AliasSeq), then isEqual would
2541     be needed.
2542 
2543     A prime example of this would be $(D Unique!(isEqual, EnumMembers!MyEnum)),
2544     which results in an $(D AliasSeq) containing the list of members of
2545     $(D MyEnum) but without any duplicate values (e.g. to use when doing code
2546     generation to create a final switch).
2547 
2548     Alternatively, code such as $(D [EnumMembers!MyEnum].sort().unique()) could
2549     be used to get a dynamic array of the enum members with no duplicate values
2550     via CTFE, thus avoiding the need for template predicates or anything from
2551     phobos.sys.meta. However, you then have a dynamic array of enum values
2552     rather than an $(D AliasSeq) of symbols for those enum members, which
2553     affects what you can do with type introspection. So, which approach is
2554     better depends on what the code needs to do with the enum members.
2555 
2556     In general, however, if code doesn't need an $(D AliasSeq), and an array of
2557     values will do the trick, then it's more efficient to operate on an array of
2558     values with CTFE and avoid using isEqual or other templates to operate on
2559     the values as an $(D AliasSeq).
2560 
2561     See_Also:
2562         $(LREF isSameSymbol)
2563         $(LREF isSameType)
2564   +/
2565 enum isEqual(alias lhs, alias rhs) = lhs == rhs;
2566 
2567 /++ Ditto +/
2568 template isEqual(alias lhs)
2569 {
2570     enum isEqual(alias rhs) = lhs == rhs;
2571 }
2572 
2573 /// It acts just like ==, but it's a template.
2574 @safe unittest
2575 {
2576     enum a = 42;
2577 
2578     static assert( isEqual!(a, 42));
2579     static assert( isEqual!(20, 10 + 10));
2580 
2581     static assert(!isEqual!(a, 120));
2582     static assert(!isEqual!(77, 19 * 7 + 2));
2583 
2584     // b cannot be read at compile time, so it won't work with isEqual.
2585     int b = 99;
2586     static assert(!__traits(compiles, isEqual!(b, 99)));
2587 }
2588 
2589 /++
2590     Comparing some of the differences between an $(D AliasSeq) of enum members
2591     and an array of enum values created from an $(D AliasSeq) of enum members.
2592   +/
2593 @safe unittest
2594 {
2595     import phobos.sys.meta : AliasSeq, Unique;
2596 
2597     enum E
2598     {
2599         a = 0,
2600         b = 22,
2601         c = 33,
2602         d = 0,
2603         e = 256,
2604         f = 33,
2605         g = 7
2606     }
2607 
2608     alias uniqueMembers = Unique!(isEqual, EnumMembers!E);
2609     static assert(uniqueMembers.length == 5);
2610 
2611     static assert(__traits(isSame, uniqueMembers[0], E.a));
2612     static assert(__traits(isSame, uniqueMembers[1], E.b));
2613     static assert(__traits(isSame, uniqueMembers[2], E.c));
2614     static assert(__traits(isSame, uniqueMembers[3], E.e));
2615     static assert(__traits(isSame, uniqueMembers[4], E.g));
2616 
2617     static assert(__traits(identifier, uniqueMembers[0]) == "a");
2618     static assert(__traits(identifier, uniqueMembers[1]) == "b");
2619     static assert(__traits(identifier, uniqueMembers[2]) == "c");
2620     static assert(__traits(identifier, uniqueMembers[3]) == "e");
2621     static assert(__traits(identifier, uniqueMembers[4]) == "g");
2622 
2623     // Same value but different symbol.
2624     static assert(uniqueMembers[0] == E.d);
2625     static assert(!__traits(isSame, uniqueMembers[0], E.d));
2626 
2627     // is expressions compare types, not symbols or values, and these AliasSeqs
2628     // contain the list of symbols for the enum members, not types, so the is
2629     // expression evaluates to false even though the symbols are the same.
2630     static assert(!is(uniqueMembers == AliasSeq!(E.a, E.b, E.c, E.e, E.g)));
2631 
2632     // Once the members are converted to an array, the types are the same, and
2633     // the values are the same, but the symbols are not the same. Instead of
2634     // being the symbols E.a, E.b, etc., they're just values with the type E
2635     // which match the values of E.a, E.b, etc.
2636     enum arr = [uniqueMembers];
2637     static assert(is(typeof(arr) == E[]));
2638 
2639     static assert(arr == [E.a, E.b, E.c, E.e, E.g]);
2640     static assert(arr == [E.d, E.b, E.f, E.e, E.g]);
2641 
2642     static assert(!__traits(isSame, arr[0], E.a));
2643     static assert(!__traits(isSame, arr[1], E.b));
2644     static assert(!__traits(isSame, arr[2], E.c));
2645     static assert(!__traits(isSame, arr[3], E.e));
2646     static assert(!__traits(isSame, arr[4], E.g));
2647 
2648     // Since arr[0] is just a value of type E, it's no longer the symbol, E.a,
2649     // even though its type is E, and its value is the same as that of E.a. And
2650     // unlike the actual members of an enum, an element of an array does not
2651     // have an identifier, so __traits(identifier, ...) doesn't work with it.
2652     static assert(!__traits(compiles, __traits(identifier, arr[0])));
2653 
2654     // Similarly, once an enum member from the AliasSeq is assigned to a
2655     // variable, __traits(identifer, ...) operates on the variable, not the
2656     // symbol from the AliasSeq or the value of the variable.
2657     auto var = uniqueMembers[0];
2658     static assert(__traits(identifier, var) == "var");
2659 
2660     // The same with a manifest constant.
2661     enum constant = uniqueMembers[0];
2662     static assert(__traits(identifier, constant) == "constant");
2663 }
2664 
2665 /++
2666     Whether the given symbols are the same symbol.
2667 
2668     All this does is $(D __traits(isSame, lhs, rhs)), so most code shouldn't
2669     use it. It's intended to be used in conjunction with templates that take a
2670     template predicate - such as those in phobos.sys.meta.
2671 
2672     The single-argument overload makes it so that it can be partially
2673     instantiated with the first argument, which will often be necessary with
2674     template predicates.
2675 
2676     See_Also:
2677         $(DDSUBLINK spec/traits, isSame, $(D __traits(isSame, lhs, rhs)))
2678         $(LREF isEqual)
2679         $(LREF isSameType)
2680   +/
2681 enum isSameSymbol(alias lhs, alias rhs) = __traits(isSame, lhs, rhs);
2682 
2683 /++ Ditto +/
2684 template isSameSymbol(alias lhs)
2685 {
2686     enum isSameSymbol(alias rhs) = __traits(isSame, lhs, rhs);
2687 }
2688 
2689 ///
2690 @safe unittest
2691 {
2692     int i;
2693     int j;
2694     real r;
2695 
2696     static assert( isSameSymbol!(i, i));
2697     static assert(!isSameSymbol!(i, j));
2698     static assert(!isSameSymbol!(i, r));
2699 
2700     static assert(!isSameSymbol!(j, i));
2701     static assert( isSameSymbol!(j, j));
2702     static assert(!isSameSymbol!(j, r));
2703 
2704     static assert(!isSameSymbol!(r, i));
2705     static assert(!isSameSymbol!(r, j));
2706     static assert( isSameSymbol!(r, r));
2707 
2708     auto foo() { return 0; }
2709     auto bar() { return 0; }
2710 
2711     static assert( isSameSymbol!(foo, foo));
2712     static assert(!isSameSymbol!(foo, bar));
2713     static assert(!isSameSymbol!(foo, i));
2714 
2715     static assert(!isSameSymbol!(bar, foo));
2716     static assert( isSameSymbol!(bar, bar));
2717     static assert(!isSameSymbol!(bar, i));
2718 
2719     // Types are symbols too. However, in most cases, they should be compared
2720     // as types, not symbols (be it with is expressions or with isSameType),
2721     // because the results aren't consistent between scalar types and
2722     // user-defined types with regards to type qualifiers when they're compared
2723     // as symbols.
2724     static assert( isSameSymbol!(double, double));
2725     static assert(!isSameSymbol!(double, const double));
2726     static assert(!isSameSymbol!(double, int));
2727     static assert( isSameSymbol!(Object, Object));
2728     static assert( isSameSymbol!(Object, const Object));
2729 
2730     static assert(!isSameSymbol!(i, int));
2731     static assert( isSameSymbol!(typeof(i), int));
2732 
2733     // Lambdas can be compared with __traits(isSame, ...),
2734     // so they can be compared with isSameSymbol.
2735     static assert( isSameSymbol!(a => a + 42, a => a + 42));
2736     static assert(!isSameSymbol!(a => a + 42, a => a + 99));
2737 
2738     // Partial instantiation allows it to be used with templates that expect
2739     // a predicate that takes only a single argument.
2740     import phobos.sys.meta : AliasSeq, indexOf;
2741     alias Types = AliasSeq!(i, j, r, int, long, foo);
2742     static assert(indexOf!(isSameSymbol!j, Types) == 1);
2743     static assert(indexOf!(isSameSymbol!int, Types) == 3);
2744     static assert(indexOf!(isSameSymbol!bar, Types) == -1);
2745 }
2746 
2747 /++
2748     Whether the given types are the same type.
2749 
2750     All this does is $(D is(T == U)), so most code shouldn't use it. It's
2751     intended to be used in conjunction with templates that take a template
2752     predicate - such as those in phobos.sys.meta.
2753 
2754     The single-argument overload makes it so that it can be partially
2755     instantiated with the first argument, which will often be necessary with
2756     template predicates.
2757 
2758     See_Also:
2759         $(LREF isEqual)
2760         $(LREF isSameSymbol)
2761   +/
2762 enum isSameType(T, U) = is(T == U);
2763 
2764 /++ Ditto +/
2765 template isSameType(T)
2766 {
2767     enum isSameType(U) = is(T == U);
2768 }
2769 
2770 ///
2771 @safe unittest
2772 {
2773     static assert( isSameType!(long, long));
2774     static assert(!isSameType!(long, const long));
2775     static assert(!isSameType!(long, string));
2776     static assert( isSameType!(string, string));
2777 
2778     int i;
2779     real r;
2780     static assert( isSameType!(int, typeof(i)));
2781     static assert(!isSameType!(int, typeof(r)));
2782 
2783     static assert(!isSameType!(real, typeof(i)));
2784     static assert( isSameType!(real, typeof(r)));
2785 
2786     // Partial instantiation allows it to be used with templates that expect
2787     // a predicate that takes only a single argument.
2788     import phobos.sys.meta : AliasSeq, indexOf;
2789     alias Types = AliasSeq!(float, string, int, double);
2790     static assert(indexOf!(isSameType!int, Types) == 2);
2791 }
2792 
2793 /++
2794     Evaluates to $(K_TRUE) ifthe given type is a delegate (and to $(K_FALSE)
2795     otherwise).
2796 
2797     This is equivalent to $(D is(T == delegate)), so most code shouldn't use
2798     it. It's intended to be used in conjunction with templates that take a
2799     template predicate - such as those in $(MREF phobos, sys, meta).
2800 
2801     Note that this does not include implicit conversions or enum types. The
2802     type itself must be a delegate.
2803 
2804     Whether taking the address of a function results in a function pointer or a
2805     delegate depends on whether the result includes a context pointer.
2806 
2807     Taking the address of a free function or a $(K_STATIC) function gives a
2808     function pointer. Taking the address of a non-$(K_STATIC) nested function
2809     gives a delegate. And the potentially confusing one is non-$(K_STATIC)
2810     member functions, because whether taking their address results in a
2811     function pointer or a delegate depends on whether the address is taken via
2812     the type or via an instance.
2813 
2814     See the documentation for $(LREF SymbolType) and $(LREF PropertyType) to
2815     see the quirks involving $(K_PROPERTY) and why either $(LREF SymbolType) or
2816     $(LREF PropertyType) should be used rather than $(K_TYPEOF) to get the type
2817     of a symbol.
2818 
2819     See_Also:
2820         $(LREF isFunction)
2821         $(LREF isFunctionPointer)
2822         $(LREF isReturn)
2823         $(LREF PropertyType)
2824         $(LREF SymbolType)
2825         $(LREF ToFunctionType)
2826   +/
2827 enum isDelegate(T) = is(T == delegate);
2828 
2829 ///
2830 @safe unittest
2831 {
2832     int var;
2833     static assert(!isDelegate!(SymbolType!var));
2834     static assert(!isDelegate!(PropertyType!var));
2835     static assert(!isDelegate!(typeof(&var)));
2836     static assert(!is(SymbolType!var == delegate));
2837     static assert(!is(PropertType!var == delegate));
2838     static assert(!is(typeof(&var) == delegate));
2839 
2840     static void func() {}
2841     static assert(!isDelegate!(SymbolType!func));
2842     static assert(!isDelegate!(typeof(&func)));
2843     static assert(!is(SymbolType!func == delegate));
2844     static assert(!is(typeof(&func) == delegate));
2845 
2846     void funcWithContext() { ++var; }
2847     static assert(!isDelegate!(SymbolType!funcWithContext));
2848     static assert( isDelegate!(typeof(&funcWithContext)));
2849     static assert(!is(SymbolType!funcWithContext == delegate));
2850     static assert( is(typeof(&funcWithContext) == delegate));
2851 
2852     int function() funcPtr;
2853     static assert(!isDelegate!(SymbolType!funcPtr));
2854     static assert(!isDelegate!(PropertyType!funcPtr));
2855     static assert(!isDelegate!(typeof(&funcPtr)));
2856     static assert(!is(SymbolType!funcPtr == delegate));
2857     static assert(!is(PropertyType!funcPtr == delegate));
2858     static assert(!is(typeof(&funcPtr) == delegate));
2859 
2860     int delegate() del;
2861     static assert( isDelegate!(SymbolType!del));
2862     static assert( isDelegate!(PropertyType!del));
2863     static assert(!isDelegate!(typeof(&del)));
2864     static assert( is(SymbolType!del == delegate));
2865     static assert( is(PropertyType!del == delegate));
2866     static assert(!is(typeof(&del) == delegate));
2867 
2868     @property static int prop() { return 0; }
2869     static assert(!isDelegate!(SymbolType!prop));
2870     static assert(!isDelegate!(PropertyType!prop));
2871     static assert(!isDelegate!(typeof(&prop)));
2872     static assert(!is(SymbolType!prop == delegate));
2873     static assert(!is(PropertyType!prop == delegate));
2874     static assert(!is(typeof(&prop) == delegate));
2875 
2876     @property int propWithContext() { return var; }
2877     static assert(!isDelegate!(SymbolType!propWithContext));
2878     static assert(!isDelegate!(PropertyType!propWithContext));
2879     static assert( isDelegate!(typeof(&propWithContext)));
2880     static assert(!is(SymbolType!propWithContext == delegate));
2881     static assert(!is(PropertyType!propWithContext == delegate));
2882     static assert( is(typeof(&propWithContext) == delegate));
2883 
2884     static int function() propFuncPtr() @property { return null; }
2885     static assert(!isDelegate!(SymbolType!propFuncPtr));
2886     static assert(!isDelegate!(PropertyType!propFuncPtr));
2887     static assert(!isDelegate!(typeof(&propFuncPtr)));
2888     static assert(!is(SymbolType!propFuncPtr == delegate));
2889     static assert(!is(PropertyType!propFuncPtr == delegate));
2890     static assert(!is(typeof(&propFuncPtr) == delegate));
2891 
2892     static int delegate() propDel() @property { return null; }
2893     static assert(!isDelegate!(SymbolType!propDel));
2894     static assert( isDelegate!(PropertyType!propDel));
2895     static assert(!isDelegate!(typeof(&propDel)));
2896     static assert(!is(SymbolType!propDel == delegate));
2897     static assert( is(PropertyType!propDel == delegate));
2898     static assert(!is(typeof(&propDel) == delegate));
2899 
2900     static struct S
2901     {
2902         void foo() {}
2903     }
2904     static assert(!isDelegate!(SymbolType!(S.foo)));
2905     static assert(!isDelegate!(typeof(&S.foo)));
2906     static assert( isDelegate!(typeof(&S.init.foo)));
2907     static assert(!is(SymbolType!(S.foo) == delegate));
2908     static assert(!is(typeof(&S.foo) == delegate));
2909     static assert( is(typeof(&S.init.foo) == delegate));
2910 
2911     struct HasContext
2912     {
2913         void foo() { ++var; }
2914     }
2915     static assert(!isDelegate!(SymbolType!(S.foo)));
2916     static assert(!isDelegate!(typeof(&S.foo)));
2917     static assert( isDelegate!(typeof(&S.init.foo)));
2918     static assert(!is(SymbolType!(S.foo) == delegate));
2919     static assert(!is(typeof(&S.foo) == delegate));
2920     static assert( is(typeof(&S.init.foo) == delegate));
2921 }
2922 
2923 /++
2924     Evaluates to $(K_TRUE) if the given type is a function (and to $(K_FALSE)
2925     otherwise).
2926 
2927     This is equivalent to $(D is(T == function)), so most code shouldn't use
2928     it. It's intended to be used in conjunction with templates that take a
2929     template predicate - such as those in $(MREF phobos, sys, meta).
2930 
2931     Note that this does not include implicit conversions or enum types. The
2932     type itself must be a function.
2933 
2934     It's not currently possible in D to type out the type of a function on its
2935     own, so normally, the only way to get a function type is to get the type of
2936     a symbol which is a function. However, $(LREF ToFunctionType) can be used
2937     to convert a function pointer type to a function type for code that needs
2938     that, though that's likely only to come up in $(K_IS) expressions.
2939 
2940     See the documentation for $(LREF SymbolType) and $(LREF PropertyType) to
2941     see the quirks involving $(K_PROPERTY) and why either $(LREF SymbolType) or
2942     $(LREF PropertyType) should be used rather than $(K_TYPEOF) to get the type
2943     of a symbol.
2944 
2945     See_Also:
2946         $(LREF isDelegate)
2947         $(LREF isFunctionPointer)
2948         $(LREF isReturn)
2949         $(LREF PropertyType)
2950         $(LREF SymbolType)
2951         $(LREF ToFunctionType)
2952   +/
2953 enum isFunction(T) = is(T == function);
2954 
2955 ///
2956 @safe unittest
2957 {
2958     int var;
2959     static assert(!isFunction!(SymbolType!var));
2960     static assert(!isFunction!(PropertyType!var));
2961     static assert(!isFunction!(typeof(&var)));
2962     static assert(!is(SymbolType!var == function));
2963     static assert(!is(PropertType!var == function));
2964     static assert(!is(typeof(&var) == function));
2965 
2966     static void func() {}
2967     static assert( isFunction!(SymbolType!func));
2968     static assert(!isFunction!(typeof(&func)));
2969     static assert( is(SymbolType!func == function));
2970     static assert(!is(typeof(&func) == function));
2971 
2972     void funcWithContext() { ++var; }
2973     static assert( isFunction!(SymbolType!funcWithContext));
2974     static assert(!isFunction!(typeof(&funcWithContext)));
2975     static assert( is(SymbolType!funcWithContext == function));
2976     static assert(!is(typeof(&funcWithContext) == function));
2977 
2978     int function() funcPtr;
2979     static assert(!isFunction!(SymbolType!funcPtr));
2980     static assert(!isFunction!(PropertyType!funcPtr));
2981     static assert(!isFunction!(typeof(&funcPtr)));
2982     static assert(!is(SymbolType!funcPtr == function));
2983     static assert(!is(PropertyType!funcPtr == function));
2984     static assert(!is(typeof(&funcPtr) == function));
2985 
2986     int delegate() del;
2987     static assert(!isFunction!(SymbolType!del));
2988     static assert(!isFunction!(PropertyType!del));
2989     static assert(!isFunction!(typeof(&del)));
2990     static assert(!is(SymbolType!del == function));
2991     static assert(!is(PropertyType!del == function));
2992     static assert(!is(typeof(&del) == function));
2993 
2994     // It's possible to get the pointers to the function and the context from a
2995     // delegate in @system code.
2996     static assert( isFunctionPointer!(typeof(SymbolType!del.funcptr)));
2997     static assert( is(typeof(SymbolType!del.ptr) == void*));
2998 
2999     @property static int prop() { return 0; }
3000     static assert( isFunction!(SymbolType!prop));
3001     static assert(!isFunction!(PropertyType!prop));
3002     static assert(!isFunction!(typeof(&prop)));
3003     static assert( is(SymbolType!prop == function));
3004     static assert(!is(PropertyType!prop == function));
3005     static assert(!is(typeof(&prop) == function));
3006 
3007     @property int propWithContext() { return var; }
3008     static assert( isFunction!(SymbolType!propWithContext));
3009     static assert(!isFunction!(PropertyType!propWithContext));
3010     static assert(!isFunction!(typeof(&propWithContext)));
3011     static assert( is(SymbolType!propWithContext == function));
3012     static assert(!is(PropertyType!propWithContext == function));
3013     static assert(!is(typeof(&propWithContext) == function));
3014 
3015     static int function() propFuncPtr() @property { return null; }
3016     static assert( isFunction!(SymbolType!propFuncPtr));
3017     static assert(!isFunction!(PropertyType!propFuncPtr));
3018     static assert(!isFunction!(typeof(&propFuncPtr)));
3019     static assert( is(SymbolType!propFuncPtr == function));
3020     static assert(!is(PropertyType!propFuncPtr == function));
3021     static assert(!is(typeof(&propFuncPtr) == function));
3022 
3023     static int delegate() propDel() @property { return null; }
3024     static assert( isFunction!(SymbolType!propDel));
3025     static assert(!isFunction!(PropertyType!propDel));
3026     static assert(!isFunction!(typeof(&propDel)));
3027     static assert( is(SymbolType!propDel == function));
3028     static assert(!is(PropertyType!propDel == function));
3029     static assert(!is(typeof(&propDel) == function));
3030 
3031     static struct S
3032     {
3033         void foo() {}
3034     }
3035     static assert( isFunction!(SymbolType!(S.foo)));
3036     static assert(!isFunction!(typeof(&S.foo)));
3037     static assert(!isFunction!(typeof(&S.init.foo)));
3038     static assert( is(SymbolType!(S.foo) == function));
3039     static assert(!is(typeof(&S.foo) == function));
3040     static assert(!is(typeof(&S.init.foo) == function));
3041 
3042     struct HasContext
3043     {
3044         void foo() { ++var; }
3045     }
3046     static assert( isFunction!(SymbolType!(S.foo)));
3047     static assert(!isFunction!(typeof(&S.foo)));
3048     static assert(!isFunction!(typeof(&S.init.foo)));
3049     static assert( is(SymbolType!(S.foo) == function));
3050     static assert(!is(typeof(&S.foo) == function));
3051     static assert(!is(typeof(&S.init.foo) == function));
3052 }
3053 
3054 /++
3055     Evaluates to $(K_TRUE) if the given type is a function pointer (and to
3056     $(K_FALSE) otherwise).
3057 
3058     Note that this does not include implicit conversions or enum types. The
3059     type itself must be a function pointer.
3060 
3061     Whether taking the address of a function results in a function pointer or a
3062     delegate depends on whether the result includes a context pointer.
3063 
3064     Taking the address of a free function or a $(K_STATIC) function gives a
3065     function pointer. Taking the address of a non-$(K_STATIC) nested function
3066     gives a delegate. And the potentially confusing one is non-$(K_STATIC)
3067     member functions, because whether taking their address results in a
3068     function pointer or a delegate depends on whether the address is taken via
3069     the type or via an instance.
3070 
3071     See the documentation for $(LREF SymbolType) and $(LREF PropertyType) to
3072     see the quirks involving $(K_PROPERTY) and why either $(LREF SymbolType) or
3073     $(LREF PropertyType) should be used rather than $(K_TYPEOF) to get the type
3074     of a symbol.
3075 
3076     See_Also:
3077         $(LREF isDelegate)
3078         $(LREF isFunction)
3079         $(LREF isReturn)
3080         $(LREF PropertyType)
3081         $(LREF SymbolType)
3082         $(LREF ToFunctionType)
3083   +/
3084 enum isFunctionPointer(T) = is(T == U*, U) && is(U == function);
3085 
3086 ///
3087 @safe unittest
3088 {
3089     int var;
3090     static assert(!isFunctionPointer!(SymbolType!var));
3091     static assert(!isFunctionPointer!(PropertyType!var));
3092     static assert(!isFunctionPointer!(typeof(&var)));
3093 
3094     static void func() {}
3095     static assert(!isFunctionPointer!(SymbolType!func));
3096     static assert( isFunctionPointer!(typeof(&func)));
3097 
3098     void funcWithContext() { ++var; }
3099     static assert(!isFunctionPointer!(SymbolType!funcWithContext));
3100     static assert(!isFunctionPointer!(typeof(&funcWithContext)));
3101 
3102     int function() funcPtr;
3103     static assert( isFunctionPointer!(SymbolType!funcPtr));
3104     static assert( isFunctionPointer!(PropertyType!funcPtr));
3105     static assert(!isFunctionPointer!(typeof(&funcPtr)));
3106 
3107     int delegate() del;
3108     static assert(!isFunctionPointer!(SymbolType!del));
3109     static assert(!isFunctionPointer!(PropertyType!del));
3110     static assert(!isFunctionPointer!(typeof(&del)));
3111 
3112     // It's possible to get the pointers to the function and the context from a
3113     // delegate in @system code.
3114     static assert( isFunctionPointer!(typeof(SymbolType!del.funcptr)));
3115     static assert( is(typeof(SymbolType!del.ptr) == void*));
3116 
3117     @property static int prop() { return 0; }
3118     static assert(!isFunctionPointer!(SymbolType!prop));
3119     static assert(!isFunctionPointer!(PropertyType!prop));
3120     static assert( isFunctionPointer!(typeof(&prop)));
3121 
3122     @property int propWithContext() { return var; }
3123     static assert(!isFunctionPointer!(SymbolType!propWithContext));
3124     static assert(!isFunctionPointer!(PropertyType!propWithContext));
3125     static assert(!isFunctionPointer!(typeof(&propWithContext)));
3126 
3127     static int function() propFuncPtr() @property { return null; }
3128     static assert(!isFunctionPointer!(SymbolType!propFuncPtr));
3129     static assert( isFunctionPointer!(PropertyType!propFuncPtr));
3130     static assert( isFunctionPointer!(typeof(&propFuncPtr)));
3131 
3132     static int delegate() propDel() @property { return null; }
3133     static assert(!isFunctionPointer!(SymbolType!propDel));
3134     static assert(!isFunctionPointer!(PropertyType!propDel));
3135     static assert( isFunctionPointer!(typeof(&propDel)));
3136 
3137     static struct S
3138     {
3139         void foo() {}
3140     }
3141     static assert(!isFunctionPointer!(SymbolType!(S.foo)));
3142     static assert( isFunctionPointer!(typeof(&S.foo)));
3143     static assert(!isFunctionPointer!(typeof(&S.init.foo)));
3144 
3145     struct HasContext
3146     {
3147         void foo() { ++var; }
3148     }
3149     static assert(!isFunctionPointer!(SymbolType!(S.foo)));
3150     static assert( isFunctionPointer!(typeof(&S.foo)));
3151     static assert(!isFunctionPointer!(typeof(&S.init.foo)));
3152 }
3153 
3154 /++
3155     Evaluates to $(K_TRUE) if the given type is a function, function pointer,
3156     or delegate (and to $(K_FALSE) otherwise).
3157 
3158     This is equivalent to $(D is(T == return)), so most code shouldn't use
3159     it. It's intended to be used in conjunction with templates that take a
3160     template predicate - such as those in $(MREF phobos, sys, meta).
3161 
3162     Note that this does not include implicit conversions or enum types. The
3163     type itself must be a function, function pointer, or delegate.
3164 
3165     See the documentation for $(LREF SymbolType) and $(LREF PropertyType) to
3166     see the quirks involving $(K_PROPERTY) and why either $(LREF SymbolType) or
3167     $(LREF PropertyType) should be used rather than $(K_TYPEOF) to get the type
3168     of a symbol.
3169 
3170     See_Also:
3171         $(LREF isDelegate)
3172         $(LREF isFunction)
3173         $(LREF isFunctionPointer)
3174         $(LREF PropertyType)
3175         $(LREF SymbolType)
3176         $(LREF ToFunctionType)
3177   +/
3178 enum isReturn(T) = is(T == return);
3179 
3180 ///
3181 @safe unittest
3182 {
3183     int var;
3184     static assert(!isReturn!(SymbolType!var));
3185     static assert(!isReturn!(PropertyType!var));
3186     static assert(!isReturn!(typeof(&var)));
3187     static assert(!is(SymbolType!var == return));
3188     static assert(!is(PropertType!var == return));
3189     static assert(!is(typeof(&var) == return));
3190 
3191     static void func() {}
3192     static assert( isReturn!(SymbolType!func));
3193     static assert( isReturn!(typeof(&func)));
3194     static assert( is(SymbolType!func == return));
3195     static assert( is(typeof(&func) == return));
3196 
3197     void funcWithContext() { ++var; }
3198     static assert( isReturn!(SymbolType!funcWithContext));
3199     static assert( isReturn!(typeof(&funcWithContext)));
3200     static assert( is(SymbolType!funcWithContext == return));
3201     static assert( is(typeof(&funcWithContext) == return));
3202 
3203     int function() funcPtr;
3204     static assert( isReturn!(SymbolType!funcPtr));
3205     static assert( isReturn!(PropertyType!funcPtr));
3206     static assert(!isReturn!(typeof(&funcPtr)));
3207     static assert( is(SymbolType!funcPtr == return));
3208     static assert( is(PropertyType!funcPtr == return));
3209     static assert(!is(typeof(&funcPtr) == return));
3210 
3211     int delegate() del;
3212     static assert( isReturn!(SymbolType!del));
3213     static assert( isReturn!(PropertyType!del));
3214     static assert(!isReturn!(typeof(&del)));
3215     static assert( is(SymbolType!del == return));
3216     static assert( is(PropertyType!del == return));
3217     static assert(!is(typeof(&del) == return));
3218 
3219     // It's possible to get the pointers to the function and the context from a
3220     // delegate in @system code.
3221     static assert( isFunctionPointer!(typeof(SymbolType!del.funcptr)));
3222     static assert( is(typeof(SymbolType!del.ptr) == void*));
3223 
3224     @property static int prop() { return 0; }
3225     static assert( isReturn!(SymbolType!prop));
3226     static assert(!isReturn!(PropertyType!prop));
3227     static assert( isReturn!(typeof(&prop)));
3228     static assert( is(SymbolType!prop == return));
3229     static assert(!is(PropertyType!prop == return));
3230     static assert( is(typeof(&prop) == return));
3231 
3232     @property int propWithContext() { return var; }
3233     static assert( isReturn!(SymbolType!propWithContext));
3234     static assert(!isReturn!(PropertyType!propWithContext));
3235     static assert( isReturn!(typeof(&propWithContext)));
3236     static assert( is(SymbolType!propWithContext == return));
3237     static assert(!is(PropertyType!propWithContext == return));
3238     static assert( is(typeof(&propWithContext) == return));
3239 
3240     static int function() propFuncPtr() @property { return null; }
3241     static assert( isReturn!(SymbolType!propFuncPtr));
3242     static assert( isReturn!(PropertyType!propFuncPtr));
3243     static assert( isReturn!(typeof(&propFuncPtr)));
3244     static assert( is(SymbolType!propFuncPtr == return));
3245     static assert( is(PropertyType!propFuncPtr == return));
3246     static assert( is(typeof(&propFuncPtr) == return));
3247 
3248     static int delegate() propDel() @property { return null; }
3249     static assert( isReturn!(SymbolType!propDel));
3250     static assert( isReturn!(PropertyType!propDel));
3251     static assert( isReturn!(typeof(&propDel)));
3252     static assert( is(SymbolType!propDel == return));
3253     static assert( is(PropertyType!propDel == return));
3254     static assert( is(typeof(&propDel) == return));
3255 
3256     static struct S
3257     {
3258         void foo() {}
3259     }
3260     static assert( isReturn!(SymbolType!(S.foo)));
3261     static assert( isReturn!(typeof(&S.foo)));
3262     static assert( isReturn!(typeof(&S.init.foo)));
3263     static assert( is(SymbolType!(S.foo) == return));
3264     static assert( is(typeof(&S.foo) == return));
3265     static assert( is(typeof(&S.init.foo) == return));
3266 
3267     struct HasContext
3268     {
3269         void foo() { ++var; }
3270     }
3271     static assert( isReturn!(SymbolType!(S.foo)));
3272     static assert( isReturn!(typeof(&S.foo)));
3273     static assert( isReturn!(typeof(&S.init.foo)));
3274     static assert( is(SymbolType!(S.foo) == return));
3275     static assert( is(typeof(&S.foo) == return));
3276     static assert( is(typeof(&S.init.foo) == return));
3277 }
3278 
3279 /++
3280     Evaluates to the return type of the given function type, function pointer
3281     type, or delegate type.
3282 
3283     Note that $(K_REF) is an attribute / storage class, not part of the type.
3284     So, when the return type is marked with $(K_REF), $(K_REF) is an attribute
3285     of the function and not part of the return type. $(LREF functionAttributes)
3286     can be used to determine whether the return value is returned by $(K_REF).
3287 
3288     Also note that in most cases, ReturnType is probably not the best solution.
3289 
3290     In situations where a function is used as a getter property, then using
3291     $(LREF PropertyType) would usually make more sense than using ReturnType,
3292     particularly since in such a situation, the property could potentially be a
3293     variable, which would not compile with ReturnType.
3294 
3295     In situations where a function may be overloaded, it can often make more
3296     sense to get the type of the expression where the function is called
3297     instead of getting the return type of the function itself - e.g.
3298     $(D typeof(foo(42))) instead of $(D ReturnType!(SymbolType!foo)), since
3299     then that will automatically get the correct overload, whereas with
3300     ReturnType, getting the return type of the correct overload would require
3301     using $(D __traits(getOverloads, foo)) and then selecting the correct
3302     overload. Getting the type of the actual function call can also can be less
3303     verbose and require fewer template instantiations, since a function call is
3304     clearly an expression and thus avoids the need for $(LREF SymbolType).
3305 
3306     So, with functions which can be used as getter properties, it's often
3307     better to use $(LREF PropertyType) than to use ReturnType, and with
3308     functions which cannot be used as getter properties, it's often better to
3309     simply get the type of the actual function call. So, ReturnType is
3310     usually not the best choice, but there are of course situations where it's
3311     exactly what's needed (e.g. if code already has the symbol or type for a
3312     specific function overload and needs to get its return type).
3313 
3314     See_Also:
3315         $(LREF functionAttributes)
3316         $(LREF PropertyType)
3317         $(LREF SymbolType)
3318   +/
3319 template ReturnType(T)
3320 if (is(T == return))
3321 {
3322     static if (is(T R == return))
3323         alias ReturnType = R;
3324     else
3325         static assert(false, "Somehow, ReturnType was instantiated with a type which has no return type");
3326 }
3327 
3328 ///
3329 @safe unittest
3330 {
3331     void foo();
3332     static assert(is(ReturnType!(SymbolType!foo) == void));
3333 
3334     int bar();
3335     static assert(is(ReturnType!(SymbolType!bar) == int));
3336 
3337     // ReturnType requires a type.
3338     static assert(!__traits(compiles, ReturnType!bar));
3339 
3340     // ReturnType requires a function type, function pointer type, or delegate
3341     // type, so the result of PropertyType only works with it if the function
3342     // returns such a type.
3343     static assert(!__traits(compiles, ReturnType!(PropertyType!bar)));
3344 
3345     string function(int) funcPtr;
3346     static assert(is(ReturnType!(SymbolType!funcPtr) == string));
3347 
3348     int delegate(string) del;
3349     static assert(is(ReturnType!(SymbolType!del) == int));
3350 
3351     int delegate(string) retDel();
3352     static assert(is(ReturnType!(SymbolType!retDel) == int delegate(string)));
3353     static assert(is(ReturnType!(PropertyType!retDel) == int));
3354     static assert(is(ReturnType!(typeof(retDel)) == int delegate(string)));
3355 
3356     @property int delegate(string) prop();
3357     static assert(is(ReturnType!(SymbolType!prop) == int delegate(string)));
3358     static assert(is(ReturnType!(PropertyType!prop) == int));
3359     static assert(is(ReturnType!(typeof(prop)) == int));
3360 
3361     ref int returnByRef();
3362     static assert(is(ReturnType!(SymbolType!returnByRef) == int));
3363 }
3364 
3365 ///
3366 @safe unittest
3367 {
3368     static struct S
3369     {
3370         void foo(string);
3371         bool foo(string, int);
3372         string foo();
3373 
3374         @property void bar(int);
3375         @property int bar();
3376     }
3377 
3378     // SymbolType gives the type of the first overload, whereas PropertyType
3379     // gives the type of the overload which can be used as a getter property
3380     // (or fails to compile if there is no such overload). Of course, the
3381     // result of PropertyType won't compile with ReturnType unless the property
3382     // gives a function pointer or delegate.
3383     // __traits(getOverloads, ...) can be used to get specific overloads (or to
3384     // iterate through all of them).
3385     {
3386         static assert( is(ReturnType!(SymbolType!(S.foo)) == void));
3387         static assert( is(PropertyType!(S.foo) == string));
3388 
3389         static assert( is(typeof(S.init.foo("")) == void));
3390         static assert( is(typeof(S.init.foo("", 42)) == bool));
3391         static assert( is(typeof(S.init.foo()) == string));
3392 
3393         alias overloads = __traits(getOverloads, S, "foo");
3394 
3395         // string foo();
3396         static assert( is(ReturnType!(SymbolType!(overloads[0])) == void));
3397 
3398         // void foo(string);
3399         static assert( is(ReturnType!(SymbolType!(overloads[1])) == bool));
3400 
3401         // void foo(string, int);
3402         static assert( is(ReturnType!(SymbolType!(overloads[2])) == string));
3403     }
3404     {
3405         static assert( is(ReturnType!(SymbolType!(S.bar)) == void));
3406         static assert( is(PropertyType!(S.bar) == int));
3407 
3408         // Normal function call syntax can be used with @property functions
3409         // (which is obviously not the intended way to use them, but it does
3410         // provide a way to distinguish between overloads).
3411         static assert( is(typeof(S.init.bar(42)) == void));
3412         static assert( is(typeof(S.init.bar()) == int));
3413 
3414         static assert( is(typeof(S.init.bar = 42) == void));
3415         static assert( is(PropertyType!(S.init.bar) == int));
3416 
3417         alias overloads = __traits(getOverloads, S, "bar");
3418 
3419         // @property void bar(int);
3420         static assert( is(ReturnType!(SymbolType!(overloads[0])) == void));
3421 
3422         // @property int bar();
3423         static assert( is(ReturnType!(SymbolType!(overloads[1])) == int));
3424     }
3425 }
3426 
3427 @safe unittest
3428 {
3429     int func1(string);
3430     static assert(is(ReturnType!(SymbolType!func1) == int));
3431     static assert(!__traits(compiles, ReturnType!func1));
3432 
3433     const(int) func2(string);
3434     static assert(is(ReturnType!(SymbolType!func2) == const int));
3435 
3436     immutable(int) func3(string);
3437     static assert(is(ReturnType!(SymbolType!func3) == immutable int));
3438 
3439     shared(int) func4(string);
3440     static assert(is(ReturnType!(SymbolType!func4) == shared int));
3441 
3442     const(shared(int)) func5(string);
3443     static assert(is(ReturnType!(SymbolType!func5) == const shared int));
3444 
3445     ref int func6(string);
3446     static assert(is(ReturnType!(SymbolType!func6) == int));
3447 
3448     ref const(int) func7(string);
3449     static assert(is(ReturnType!(SymbolType!func7) == const int));
3450 
3451     static struct S
3452     {
3453         real foo();
3454         real bar() const;
3455         inout(real) baz() inout;
3456         ref real func() shared;
3457     }
3458     static assert(is(ReturnType!(SymbolType!(S.foo)) == real));
3459     static assert(is(ReturnType!(SymbolType!(S.bar)) == real));
3460     static assert(is(ReturnType!(SymbolType!(S.baz)) == inout real));
3461     static assert(is(ReturnType!(SymbolType!(S.func)) == real));
3462 
3463     static class C
3464     {
3465         byte foo() { assert(0); }
3466         byte bar() const { assert(0); }
3467         inout(byte) baz() inout { assert(0); }
3468         ref byte func() shared { assert(0); }
3469     }
3470     static assert(is(ReturnType!(SymbolType!(C.foo)) == byte));
3471     static assert(is(ReturnType!(SymbolType!(C.bar)) == byte));
3472     static assert(is(ReturnType!(SymbolType!(C.baz)) == inout byte));
3473     static assert(is(ReturnType!(SymbolType!(C.func)) == byte));
3474 
3475     static struct NoCopy
3476     {
3477         @disable this(this);
3478     }
3479     static assert(!__traits(isCopyable, NoCopy));
3480 
3481     NoCopy retNC();
3482     static assert(is(ReturnType!(SymbolType!retNC) == NoCopy));
3483 }
3484 
3485 /++
3486     Converts a function type, function pointer type, or delegate type to the
3487     corresponding function type.
3488 
3489     For a function, the result is the same as the given type.
3490 
3491     For a function pointer or delegate, the result is the same as it would be
3492     for a function with the same return type, the same set of parameters, and
3493     the same set of attributes.
3494 
3495     Another way to look at it would be that it's the type that comes from
3496     dereferencing the function pointer. And while it's not technically possible
3497     to dereference a delegate, it's conceptually the same thing, since a
3498     delegate is essentially a fat pointer to a function in the sense that it
3499     contains a pointer to a function and a pointer to the function's context.
3500     The result of ToFunctionType is the type of that function.
3501 
3502     Note that code which has a symbol which is a function should use
3503     $(LREF SymbolType) rather than $(K_TYPEOF) to get the type of the function
3504     in order to avoid issues with regards to $(K_PROPERTY) (see the
3505     documentation for $(LREF SymbolType) for details).
3506 
3507     See_Also:
3508         $(LREF SymbolType)
3509   +/
3510 template ToFunctionType(T)
3511 if (is(T == return))
3512 {
3513     // Function pointers.
3514     static if (is(T == U*, U) && is(U == function))
3515         alias ToFunctionType = U;
3516     // Delegates.
3517     else static if (is(T U == delegate))
3518         alias ToFunctionType = U;
3519     // Functions.
3520     else
3521         alias ToFunctionType = T;
3522 }
3523 
3524 ///
3525 @safe unittest
3526 {
3527     static string func(int) { return ""; }
3528     auto funcPtr = &func;
3529 
3530     static assert( is(ToFunctionType!(SymbolType!func) == SymbolType!func));
3531     static assert( is(ToFunctionType!(SymbolType!funcPtr) == SymbolType!func));
3532     static assert(!is(SymbolType!funcPtr == function));
3533     static assert( is(ToFunctionType!(SymbolType!funcPtr) == function));
3534 
3535     int var;
3536     int funcWithContext(string) { return var; }
3537     auto funcDel = &funcWithContext;
3538 
3539     static assert( is(ToFunctionType!(SymbolType!funcWithContext) ==
3540                       SymbolType!funcWithContext));
3541     static assert( is(ToFunctionType!(SymbolType!funcDel) ==
3542                       SymbolType!funcWithContext));
3543     static assert( is(SymbolType!funcWithContext == function));
3544     static assert(!is(SymbolType!funcDel == function));
3545     static assert( is(SymbolType!funcDel == delegate));
3546     static assert( is(ToFunctionType!(SymbolType!funcDel) == function));
3547 
3548     static @property int prop() { return 0; }
3549     static assert( is(SymbolType!prop == function));
3550     static assert(!is(SymbolType!prop == delegate));
3551     static assert( is(SymbolType!prop == return));
3552     static assert( is(SymbolType!prop ==
3553                       ToFunctionType!(int function() @property @safe pure
3554                                                      nothrow @nogc)));
3555     static assert( is(ToFunctionType!(SymbolType!prop) == SymbolType!prop));
3556 
3557     // This is an example of why SymbolType should be used rather than typeof
3558     // when using ToFunctionType (or getting the type of any symbol which might
3559     // be a function when you want the actual type of the symbol and don't want
3560     // to end up with its return type instead).
3561     static assert( is(typeof(prop) == int));
3562     static assert(!is(typeof(prop) == function));
3563     static assert(!__traits(compiles, ToFunctionType!(typeof(prop))));
3564 
3565     auto propPtr = ∝
3566     static assert(!is(typeof(propPtr) == function));
3567     static assert(!is(SymbolType!propPtr == function));
3568     static assert( isFunctionPointer!(typeof(propPtr)));
3569     static assert( is(ToFunctionType!(SymbolType!propPtr) == function));
3570 
3571     static assert( is(SymbolType!propPtr ==
3572                       int function() @property @safe pure nothrow @nogc));
3573     static assert(!is(ToFunctionType!(SymbolType!propPtr) ==
3574                       int function() @property @safe pure nothrow @nogc));
3575     static assert( is(ToFunctionType!(SymbolType!propPtr) ==
3576                       ToFunctionType!(int function() @property @safe pure
3577                                                      nothrow @nogc)));
3578 
3579     @property void propWithContext(int i) { var += i; }
3580     static assert( is(SymbolType!propWithContext == function));
3581     static assert( is(SymbolType!propWithContext ==
3582                       ToFunctionType!(void function(int) @property @safe pure
3583                                                          nothrow @nogc)));
3584     static assert( is(ToFunctionType!(SymbolType!propWithContext) ==
3585                       SymbolType!propWithContext));
3586 
3587     // typeof fails to compile with setter properties, complaining about there
3588     // not being enough arguments, because it's treating the function as an
3589     // expression - and since such an expression would call the function, the
3590     // expression isn't valid if there aren't enough function arguments.
3591     static assert(!__traits(compiles, typeof(propWithContext)));
3592 
3593     auto propDel = &propWithContext;
3594     static assert(!is(SymbolType!propDel == function));
3595     static assert( is(SymbolType!propDel == delegate));
3596     static assert( is(SymbolType!propDel == return));
3597     static assert( is(ToFunctionType!(SymbolType!propDel) == function));
3598     static assert( is(ToFunctionType!(SymbolType!propDel) ==
3599                       SymbolType!propWithContext));
3600 
3601     static assert( is(SymbolType!propDel ==
3602                       void delegate(int) @property @safe pure nothrow @nogc));
3603     static assert(!is(ToFunctionType!(SymbolType!propDel) ==
3604                       void delegate(int) @property @safe pure nothrow @nogc));
3605     static assert(!is(ToFunctionType!(SymbolType!propDel) ==
3606                       void function(int) @property @safe pure nothrow @nogc));
3607     static assert( is(ToFunctionType!(SymbolType!propDel) ==
3608                       ToFunctionType!(void function(int) @property @safe pure
3609                                                          nothrow @nogc)));
3610 
3611     // Delegates have a funcptr property and a ptr property (which can only be
3612     // used in @system code) which give the pointer to the function and the
3613     // pointer to the context respectively.
3614     static assert( is(ToFunctionType!(SymbolType!propDel) ==
3615                       typeof(*SymbolType!propDel.funcptr)));
3616     static assert( is(typeof(SymbolType!propDel.ptr) == void*));
3617 
3618     static struct S
3619     {
3620         string foo(int);
3621         string bar(int, int);
3622         @property void prop(string);
3623     }
3624 
3625     static assert( is(ToFunctionType!(SymbolType!(S.foo)) ==
3626                       ToFunctionType!(string function(int))));
3627     static assert( is(ToFunctionType!(SymbolType!(S.bar)) ==
3628                       ToFunctionType!(string function(int, int))));
3629     static assert( is(ToFunctionType!(SymbolType!(S.prop)) ==
3630                       ToFunctionType!(void function(string) @property)));
3631 }
3632 
3633 @safe unittest
3634 {
3635     // Unfortunately, in this case, we get linker errors when taking the address
3636     // of the functions if we avoid inference by not giving function bodies.
3637     // So if we don't want to list all of those attributes in the tests, we have
3638     // to stop the inference in another way.
3639     static int var;
3640     static void killAttributes() @system { ++var; throw new Exception("message"); }
3641 
3642     static struct S
3643     {
3644         int func1() { killAttributes(); return 0; }
3645         void func2(int) { killAttributes(); }
3646 
3647         static int func3() { killAttributes(); return 0; }
3648         static void func4(int) { killAttributes(); }
3649 
3650         @property int func5() { killAttributes(); return 0; }
3651         @property void func6(int) { killAttributes(); }
3652     }
3653 
3654     static assert( is(SymbolType!(S.func1) == ToFunctionType!(int function())));
3655     static assert( is(SymbolType!(S.func2) == ToFunctionType!(void function(int))));
3656     static assert( is(SymbolType!(S.func3) == ToFunctionType!(int function())));
3657     static assert( is(SymbolType!(S.func4) == ToFunctionType!(void function(int))));
3658     static assert( is(SymbolType!(S.func5) == ToFunctionType!(int function() @property)));
3659     static assert( is(SymbolType!(S.func6) == ToFunctionType!(void function(int) @property)));
3660 
3661     static assert( is(ToFunctionType!(SymbolType!(S.func1)) == ToFunctionType!(int function())));
3662     static assert( is(ToFunctionType!(SymbolType!(S.func2)) == ToFunctionType!(void function(int))));
3663     static assert( is(ToFunctionType!(SymbolType!(S.func3)) == ToFunctionType!(int function())));
3664     static assert( is(ToFunctionType!(SymbolType!(S.func4)) == ToFunctionType!(void function(int))));
3665     static assert( is(ToFunctionType!(SymbolType!(S.func5)) == ToFunctionType!(int function() @property)));
3666     static assert( is(ToFunctionType!(SymbolType!(S.func6)) ==
3667                       ToFunctionType!(void function(int) @property)));
3668 
3669     auto ptr1 = &S.init.func1;
3670     auto ptr2 = &S.init.func2;
3671     auto ptr3 = &S.func3;
3672     auto ptr4 = &S.func4;
3673     auto ptr5 = &S.init.func5;
3674     auto ptr6 = &S.init.func6;
3675 
3676     // For better or worse, static member functions can be accessed through
3677     // instance of the type as well as through the type.
3678     auto ptr3Instance = &S.init.func3;
3679     auto ptr4Instance = &S.init.func4;
3680 
3681     static assert( is(SymbolType!ptr1 == int delegate()));
3682     static assert( is(SymbolType!ptr2 == void delegate(int)));
3683     static assert( is(SymbolType!ptr3 == int function()));
3684     static assert( is(SymbolType!ptr4 == void function(int)));
3685     static assert( is(SymbolType!ptr5 == int delegate() @property));
3686     static assert( is(SymbolType!ptr6 == void delegate(int) @property));
3687 
3688     static assert( is(SymbolType!ptr3Instance == int function()));
3689     static assert( is(SymbolType!ptr4Instance == void function(int)));
3690 
3691     static assert( is(ToFunctionType!(SymbolType!ptr1) == ToFunctionType!(int function())));
3692     static assert( is(ToFunctionType!(SymbolType!ptr2) == ToFunctionType!(void function(int))));
3693     static assert( is(ToFunctionType!(SymbolType!ptr3) == ToFunctionType!(int function())));
3694     static assert( is(ToFunctionType!(SymbolType!ptr4) == ToFunctionType!(void function(int))));
3695     static assert( is(ToFunctionType!(SymbolType!ptr5) == ToFunctionType!(int function() @property)));
3696     static assert( is(ToFunctionType!(SymbolType!ptr6) == ToFunctionType!(void function(int) @property)));
3697 
3698     static assert( is(ToFunctionType!(SymbolType!ptr3Instance) == ToFunctionType!(int function())));
3699     static assert( is(ToFunctionType!(SymbolType!ptr4Instance) == ToFunctionType!(void function(int))));
3700 }
3701 
3702 /++
3703     Evaluates to an $(D AliasSeq) of the names (as $(D string)s) of the member
3704     variables of an aggregate type (i.e. a struct, class, interface, or union).
3705 
3706     These are fields which take up memory space within an instance of the type
3707     (i.e. not enums / manifest constants, since they don't take up memory
3708     space, and not static member variables, since they don't take up memory
3709     space within an instance).
3710 
3711     Hidden fields (like the virtual function table pointer or the context
3712     pointer for nested types) are not included.
3713 
3714     For classes, only the direct member variables are included and not those
3715     of any base classes.
3716 
3717     For interfaces, the result of FieldNames is always empty, because
3718     interfaces cannot have member variables. However, because interfaces are
3719     aggregate types, they work with FieldNames for consistency so that code
3720     that's written to work on aggregate types doesn't have to worry about
3721     whether it's dealing with an interface.
3722 
3723     See_Also:
3724         $(LREF FieldSymbols)
3725         $(LREF FieldTypes)
3726         $(DDSUBLINK spec/struct.html, struct_instance_properties, $(D tupleof))
3727   +/
3728 template FieldNames(T)
3729 if (isAggregateType!T)
3730 {
3731     import phobos.sys.meta : AliasSeq;
3732 
3733     static if (is(T == struct) && __traits(isNested, T))
3734         private alias Fields = AliasSeq!(T.tupleof[0 .. $ - 1]);
3735     else
3736         private alias Fields = T.tupleof;
3737 
3738     alias FieldNames = AliasSeq!();
3739     static foreach (Field; Fields)
3740         FieldNames = AliasSeq!(FieldNames, Field.stringof);
3741 }
3742 
3743 ///
3744 @safe unittest
3745 {
3746     import phobos.sys.meta : AliasSeq;
3747 
3748     struct S
3749     {
3750         int x;
3751         float y;
3752     }
3753     static assert(FieldNames!S == AliasSeq!("x", "y"));
3754 
3755     // Since the AliasSeq contains values, all of which are of the same type,
3756     // it can be used to create a dynamic array, which would be more
3757     // efficient than operating on an AliasSeq in the cases where an
3758     // AliasSeq is not necessary.
3759     static assert([FieldNames!S] == ["x", "y"]);
3760 
3761     class C
3762     {
3763         // static variables are not included.
3764         static int var;
3765 
3766         // Manifest constants are not included.
3767         enum lang = "dlang";
3768 
3769         // Functions are not included, even if they're @property functions.
3770         @property int foo() { return 42; }
3771 
3772         string s;
3773         int i;
3774         int[] arr;
3775     }
3776     static assert(FieldNames!C == AliasSeq!("s", "i", "arr"));
3777 
3778     static assert([FieldNames!C] == ["s", "i", "arr"]);
3779 
3780     // Only direct member variables are included. Member variables from any base
3781     // classes are not.
3782     class D : C
3783     {
3784         real r;
3785     }
3786     static assert(FieldNames!D == AliasSeq!"r");
3787 
3788     static assert([FieldNames!D] == ["r"]);
3789 
3790     // FieldNames will always be empty for an interface, since it's not legal
3791     // for interfaces to have member variables.
3792     interface I
3793     {
3794     }
3795     static assert(FieldNames!I.length == 0);
3796 
3797     union U
3798     {
3799         int i;
3800         double d;
3801         long l;
3802         S s;
3803     }
3804     static assert(FieldNames!U == AliasSeq!("i", "d", "l", "s"));
3805 
3806     static assert([FieldNames!U] == ["i", "d", "l", "s"]);;
3807 
3808     // FieldNames only operates on aggregate types.
3809     static assert(!__traits(compiles, FieldNames!int));
3810     static assert(!__traits(compiles, FieldNames!(S*)));
3811     static assert(!__traits(compiles, FieldNames!(C[])));
3812 }
3813 
3814 @safe unittest
3815 {
3816     import phobos.sys.meta : AliasSeq;
3817 
3818     {
3819         static struct S0 {}
3820         static assert(FieldNames!S0.length == 0);
3821 
3822         static struct S1 { int a; }
3823         static assert(FieldNames!S1 == AliasSeq!"a");
3824 
3825         static struct S2 { int a; string b; }
3826         static assert(FieldNames!S2 == AliasSeq!("a", "b"));
3827 
3828         static struct S3 { int a; string b; real c; }
3829         static assert(FieldNames!S3 == AliasSeq!("a", "b", "c"));
3830     }
3831     {
3832         int i;
3833         struct S0 { void foo() { i = 0; }}
3834         static assert(FieldNames!S0.length == 0);
3835         static assert(__traits(isNested, S0));
3836 
3837         struct S1 { int a; void foo() { i = 0; } }
3838         static assert(FieldNames!S1 == AliasSeq!"a");
3839         static assert(__traits(isNested, S1));
3840 
3841         struct S2 { int a; string b; void foo() { i = 0; } }
3842         static assert(FieldNames!S2 == AliasSeq!("a", "b"));
3843         static assert(__traits(isNested, S2));
3844 
3845         struct S3 { int a; string b; real c; void foo() { i = 0; } }
3846         static assert(FieldNames!S3 == AliasSeq!("a", "b", "c"));
3847         static assert(__traits(isNested, S3));
3848     }
3849     {
3850         static class C0 {}
3851         static assert(FieldNames!C0.length == 0);
3852 
3853         static class C1 { int a; }
3854         static assert(FieldNames!C1 == AliasSeq!"a");
3855 
3856         static class C2 { int a; string b; }
3857         static assert(FieldNames!C2 == AliasSeq!("a", "b"));
3858 
3859         static class C3 { int a; string b; real c; }
3860         static assert(FieldNames!C3 == AliasSeq!("a", "b", "c"));
3861 
3862         static class D0 : C3 {}
3863         static assert(FieldNames!D0.length == 0);
3864 
3865         static class D1 : C3 { bool x; }
3866         static assert(FieldNames!D1 == AliasSeq!"x");
3867 
3868         static class D2 : C3 { bool x; int* y; }
3869         static assert(FieldNames!D2 == AliasSeq!("x", "y"));
3870 
3871         static class D3 : C3 { bool x; int* y; short[] z; }
3872         static assert(FieldNames!D3 == AliasSeq!("x", "y", "z"));
3873     }
3874     {
3875         int i;
3876         class C0 { void foo() { i = 0; }}
3877         static assert(FieldNames!C0.length == 0);
3878         static assert(__traits(isNested, C0));
3879 
3880         class C1 { int a; void foo() { i = 0; } }
3881         static assert(FieldNames!C1 == AliasSeq!"a");
3882         static assert(__traits(isNested, C1));
3883 
3884         class C2 { int a; string b; void foo() { i = 0; } }
3885         static assert(FieldNames!C2 == AliasSeq!("a", "b"));
3886         static assert(__traits(isNested, C2));
3887 
3888         class C3 { int a; string b; real c; void foo() { i = 0; } }
3889         static assert(FieldNames!C3 == AliasSeq!("a", "b", "c"));
3890         static assert(__traits(isNested, C3));
3891 
3892         class D0 : C3 {}
3893         static assert(FieldNames!D0.length == 0);
3894         static assert(__traits(isNested, D0));
3895 
3896         class D1 : C3 { bool x; }
3897         static assert(FieldNames!D1 == AliasSeq!"x");
3898         static assert(__traits(isNested, D1));
3899 
3900         class D2 : C3 { bool x; int* y; }
3901         static assert(FieldNames!D2 == AliasSeq!("x", "y"));
3902         static assert(__traits(isNested, D2));
3903 
3904         class D3 : C3 { bool x; int* y; short[] z; }
3905         static assert(FieldNames!D3 == AliasSeq!("x", "y", "z"));
3906         static assert(__traits(isNested, D3));
3907     }
3908     {
3909         static union U0 {}
3910         static assert(FieldNames!U0.length == 0);
3911 
3912         static union U1 { int a; }
3913         static assert(FieldNames!U1 == AliasSeq!"a");
3914 
3915         static union U2 { int a; string b; }
3916         static assert(FieldNames!U2 == AliasSeq!("a", "b"));
3917 
3918         static union U3 { int a; string b; real c; }
3919         static assert(FieldNames!U3 == AliasSeq!("a", "b", "c"));
3920     }
3921     {
3922         static struct S
3923         {
3924             enum e = 42;
3925             static str = "foobar";
3926 
3927             string name() { return "foo"; }
3928 
3929             int[] arr;
3930 
3931             struct Inner1 { int i; }
3932 
3933             static struct Inner2 { long gnol; }
3934 
3935             union { int a; string b; }
3936 
3937             alias Foo = Inner1;
3938         }
3939 
3940         static assert(FieldNames!S == AliasSeq!("arr", "a", "b"));
3941         static assert(FieldNames!(const S) == AliasSeq!("arr", "a", "b"));
3942         static assert(FieldNames!(S.Inner1) == AliasSeq!"i");
3943         static assert(FieldNames!(S.Inner2) == AliasSeq!"gnol");
3944     }
3945 }
3946 
3947 /++
3948     Evaluates to an $(D AliasSeq) of the symbols for the member variables of an
3949     aggregate type (i.e. a struct, class, interface, or union).
3950 
3951     These are fields which take up memory space within an instance of the type
3952     (i.e. not enums / manifest constants, since they don't take up memory
3953     space, and not static member variables, since they don't take up memory
3954     space within an instance).
3955 
3956     Hidden fields (like the virtual function table pointer or the context
3957     pointer for nested types) are not included.
3958 
3959     For classes, only the direct member variables are included and not those
3960     of any base classes.
3961 
3962     For interfaces, the result of FieldSymbols is always empty, because
3963     interfaces cannot have member variables. However, because interfaces are
3964     aggregate types, they work with FieldSymbols for consistency so that code
3965     that's written to work on aggregate types doesn't have to worry about
3966     whether it's dealing with an interface.
3967 
3968     In most cases, $(D FieldSymbols!T) has the same result as $(D T.tupleof).
3969     The difference is that for nested structs with a context pointer,
3970     $(D T.tupleof) includes the context pointer, whereas $(D FieldSymbols!T)
3971     does not. For non-nested structs, and for classes, interfaces, and unions,
3972     $(D FieldSymbols!T) and $(D T.tupleof) are the same.
3973 
3974     So, for most cases, $(D T.tupleof) is sufficient and avoids instantiating
3975     an additional template, but FieldSymbols is provided so that the code that
3976     needs to avoid including context pointers in the list of fields can do so
3977     without the programmer having to figure how to do that correctly. It also
3978     provides a template that's equivalent to what $(LREF FieldNames) and
3979     $(LREF FieldTypes) do in terms of which fields it gives (the difference of
3980     course then being whether you get the symbols, names, or types for the
3981     fields), whereas the behavior for $(D tupleof) is subtly different.
3982 
3983     See_Also:
3984         $(LREF FieldNames)
3985         $(LREF FieldTypes)
3986         $(DDSUBLINK spec/struct.html, struct_instance_properties, $(D tupleof))
3987         $(DDSUBLINK spec/traits, isNested, $(D __traits(isNested, ...))).
3988         $(DDSUBLINK spec/traits, isSame, $(D __traits(isSame, ...))).
3989   +/
3990 template FieldSymbols(T)
3991 if (isAggregateType!T)
3992 {
3993     static if (is(T == struct) && __traits(isNested, T))
3994     {
3995         import phobos.sys.meta : AliasSeq;
3996         alias FieldSymbols = AliasSeq!(T.tupleof[0 .. $ - 1]);
3997     }
3998     else
3999         alias FieldSymbols = T.tupleof;
4000 }
4001 
4002 ///
4003 @safe unittest
4004 {
4005     import phobos.sys.meta : AliasSeq;
4006 
4007     struct S
4008     {
4009         int x;
4010         float y;
4011     }
4012     static assert(__traits(isSame, FieldSymbols!S, AliasSeq!(S.x, S.y)));
4013 
4014     // FieldSymbols!S and S.tupleof are the same, because S is not nested.
4015     static assert(__traits(isSame, FieldSymbols!S, S.tupleof));
4016 
4017     // Note that type qualifiers _should_ be passed on to the result, but due
4018     // to https://issues.dlang.org/show_bug.cgi?id=24516, they aren't.
4019     // FieldTypes does not have this problem, because it aliases the types
4020     // rather than the symbols, so if you need the types from the symbols, you
4021     // should use either FieldTypes or tupleof until the compiler bug has been
4022     // fixed (and if you use tupleof, you need to avoid aliasing the result
4023     // before getting the types from it).
4024     static assert(is(typeof(FieldSymbols!S[0]) == int));
4025 
4026     // These currently fail when they shouldn't:
4027     //static assert(is(typeof(FieldSymbols!(const S)[0]) == const int));
4028     //static assert(is(typeof(FieldSymbols!(shared S)[0]) == shared int));
4029 
4030     class C
4031     {
4032         // static variables are not included.
4033         static int var;
4034 
4035         // Manifest constants are not included.
4036         enum lang = "dlang";
4037 
4038         // Functions are not included, even if they're @property functions.
4039         @property int foo() { return 42; }
4040 
4041         string s;
4042         int i;
4043         int[] arr;
4044     }
4045     static assert(__traits(isSame, FieldSymbols!C, AliasSeq!(C.s, C.i, C.arr)));
4046 
4047     // FieldSymbols!C and C.tupleof have the same symbols, because they are
4048     // always the same for classes.
4049     static assert(__traits(isSame, FieldSymbols!C, C.tupleof));
4050 
4051     // Only direct member variables are included. Member variables from any base
4052     // classes are not.
4053     class D : C
4054     {
4055         real r;
4056     }
4057     static assert(__traits(isSame, FieldSymbols!D, AliasSeq!(D.r)));
4058     static assert(__traits(isSame, FieldSymbols!D, D.tupleof));
4059 
4060     // FieldSymbols will always be empty for an interface, since it's not legal
4061     // for interfaces to have member variables.
4062     interface I
4063     {
4064     }
4065     static assert(FieldSymbols!I.length == 0);
4066     static assert(I.tupleof.length == 0);
4067 
4068     union U
4069     {
4070         int i;
4071         double d;
4072         long l;
4073         S s;
4074     }
4075     static assert(__traits(isSame, FieldSymbols!U, AliasSeq!(U.i, U.d, U.l, U.s)));
4076 
4077     // FieldSymbols!C and C.tupleof have the same symbols, because they are
4078     // always the same for unions.
4079     static assert(__traits(isSame, FieldSymbols!U, U.tupleof));
4080 
4081     // FieldSymbols only operates on aggregate types.
4082     static assert(!__traits(compiles, FieldSymbols!int));
4083     static assert(!__traits(compiles, FieldSymbols!(S*)));
4084     static assert(!__traits(compiles, FieldSymbols!(C[])));
4085 }
4086 
4087 /// Some examples with nested types.
4088 @safe unittest
4089 {
4090     import phobos.sys.meta : AliasSeq;
4091 
4092     int outside;
4093 
4094     struct S
4095     {
4096         long l;
4097         string s;
4098 
4099         void foo() { outside = 2; }
4100     }
4101     static assert(__traits(isNested, S));
4102     static assert(__traits(isSame, FieldSymbols!S, AliasSeq!(S.l, S.s)));
4103 
4104     // FieldSymbols!S and S.tupleof are not the same, because S is nested, and
4105     // the context pointer to the outer scope is included in S.tupleof, whereas
4106     // it is excluded from FieldSymbols!S.
4107     static assert(__traits(isSame, S.tupleof[0 .. $ - 1], AliasSeq!(S.l, S.s)));
4108     static assert(S.tupleof[$ - 1].stringof == "this");
4109 
4110     class C
4111     {
4112         bool b;
4113         int* ptr;
4114 
4115         void foo() { outside = 7; }
4116     }
4117     static assert(__traits(isNested, C));
4118     static assert(__traits(isSame, FieldSymbols!C, AliasSeq!(C.b, C.ptr)));
4119 
4120     // FieldSymbols!C and C.tupleof have the same symbols, because they are
4121     // always the same for classes. No context pointer is provided as part of
4122     // tupleof for nested classes.
4123     static assert(__traits(isSame, FieldSymbols!C, C.tupleof));
4124 
4125     // __traits(isNested, ...) is never true for interfaces or unions, since
4126     // they cannot have a context pointer to an outer scope. So, tupleof and
4127     // FieldSymbols will always be the same for interfaces and unions.
4128 }
4129 
4130 @safe unittest
4131 {
4132     import phobos.sys.meta : AliasSeq;
4133 
4134     {
4135         static struct S0 {}
4136         static assert(FieldSymbols!S0.length == 0);
4137 
4138         static struct S1 { int a; }
4139         static assert(__traits(isSame, FieldSymbols!S1, AliasSeq!(S1.a)));
4140 
4141         static struct S2 { int a; string b; }
4142         static assert(__traits(isSame, FieldSymbols!S2, AliasSeq!(S2.a, S2.b)));
4143 
4144         static struct S3 { int a; string b; real c; }
4145         static assert(__traits(isSame, FieldSymbols!S3, AliasSeq!(S3.a, S3.b, S3.c)));
4146     }
4147     {
4148         int i;
4149         struct S0 { void foo() { i = 0; }}
4150         static assert(FieldSymbols!S0.length == 0);
4151         static assert(__traits(isNested, S0));
4152 
4153         struct S1 { int a; void foo() { i = 0; } }
4154         static assert(__traits(isSame, FieldSymbols!S1, AliasSeq!(S1.a)));
4155         static assert(__traits(isNested, S1));
4156 
4157         struct S2 { int a; string b; void foo() { i = 0; } }
4158         static assert(__traits(isSame, FieldSymbols!S2, AliasSeq!(S2.a, S2.b)));
4159         static assert(__traits(isNested, S2));
4160 
4161         struct S3 { int a; string b; real c; void foo() { i = 0; } }
4162         static assert(__traits(isSame, FieldSymbols!S3, AliasSeq!(S3.a, S3.b, S3.c)));
4163         static assert(__traits(isNested, S3));
4164     }
4165     {
4166         static class C0 {}
4167         static assert(FieldSymbols!C0.length == 0);
4168 
4169         static class C1 { int a; }
4170         static assert(__traits(isSame, FieldSymbols!C1, AliasSeq!(C1.a)));
4171 
4172         static class C2 { int a; string b; }
4173         static assert(__traits(isSame, FieldSymbols!C2, AliasSeq!(C2.a, C2.b)));
4174 
4175         static class C3 { int a; string b; real c; }
4176         static assert(__traits(isSame, FieldSymbols!C3, AliasSeq!(C3.a, C3.b, C3.c)));
4177 
4178         static class D0 : C3 {}
4179         static assert(FieldSymbols!D0.length == 0);
4180 
4181         static class D1 : C3 { bool x; }
4182         static assert(__traits(isSame, FieldSymbols!D1, AliasSeq!(D1.x)));
4183 
4184         static class D2 : C3 { bool x; int* y; }
4185         static assert(__traits(isSame, FieldSymbols!D2, AliasSeq!(D2.x, D2.y)));
4186 
4187         static class D3 : C3 { bool x; int* y; short[] z; }
4188         static assert(__traits(isSame, FieldSymbols!D3, AliasSeq!(D3.x, D3.y, D3.z)));
4189     }
4190     {
4191         int i;
4192         class C0 { void foo() { i = 0; }}
4193         static assert(FieldSymbols!C0.length == 0);
4194         static assert(__traits(isNested, C0));
4195 
4196         class C1 { int a; void foo() { i = 0; } }
4197         static assert(__traits(isSame, FieldSymbols!C1, AliasSeq!(C1.a)));
4198         static assert(__traits(isNested, C1));
4199 
4200         class C2 { int a; string b; void foo() { i = 0; } }
4201         static assert(__traits(isSame, FieldSymbols!C2, AliasSeq!(C2.a, C2.b)));
4202         static assert(__traits(isNested, C2));
4203 
4204         class C3 { int a; string b; real c; void foo() { i = 0; } }
4205         static assert(__traits(isSame, FieldSymbols!C3, AliasSeq!(C3.a, C3.b, C3.c)));
4206         static assert(__traits(isNested, C3));
4207 
4208         class D0 : C3 {}
4209         static assert(FieldSymbols!D0.length == 0);
4210         static assert(__traits(isNested, D0));
4211 
4212         class D1 : C3 { bool x; }
4213         static assert(__traits(isSame, FieldSymbols!D1, AliasSeq!(D1.x)));
4214         static assert(__traits(isNested, D1));
4215 
4216         class D2 : C3 { bool x; int* y; }
4217         static assert(__traits(isSame, FieldSymbols!D2, AliasSeq!(D2.x, D2.y)));
4218         static assert(__traits(isNested, D2));
4219 
4220         class D3 : C3 { bool x; int* y; short[] z; }
4221         static assert(__traits(isSame, FieldSymbols!D3, AliasSeq!(D3.x, D3.y, D3.z)));
4222         static assert(__traits(isNested, D3));
4223     }
4224     {
4225         static union U0 {}
4226         static assert(FieldSymbols!U0.length == 0);
4227 
4228         static union U1 { int a; }
4229         static assert(__traits(isSame, FieldSymbols!U1, AliasSeq!(U1.a)));
4230 
4231         static union U2 { int a; string b; }
4232         static assert(__traits(isSame, FieldSymbols!U2, AliasSeq!(U2.a, U2.b)));
4233 
4234         static union U3 { int a; string b; real c; }
4235         static assert(__traits(isSame, FieldSymbols!U3, AliasSeq!(U3.a, U3.b, U3.c)));
4236     }
4237     {
4238         static struct S
4239         {
4240             enum e = 42;
4241             static str = "foobar";
4242 
4243             string name() { return "foo"; }
4244 
4245             int[] arr;
4246 
4247             struct Inner1 { int i; }
4248 
4249             static struct Inner2 { long gnol; }
4250 
4251             union { int a; string b; }
4252 
4253             alias Foo = Inner1;
4254         }
4255 
4256         static assert(__traits(isSame, FieldSymbols!S, AliasSeq!(S.arr, S.a, S.b)));
4257         static assert(__traits(isSame, FieldSymbols!(const S), AliasSeq!(S.arr, S.a, S.b)));
4258         static assert(__traits(isSame, FieldSymbols!(S.Inner1), AliasSeq!(S.Inner1.i)));
4259         static assert(__traits(isSame, FieldSymbols!(S.Inner2), AliasSeq!(S.Inner2.gnol)));
4260     }
4261 }
4262 
4263 /++
4264     Evaluates to an $(D AliasSeq) of the types of the member variables of an
4265     aggregate type (i.e. a struct, class, interface, or union).
4266 
4267     These are fields which take up memory space within an instance of the type
4268     (i.e. not enums / manifest constants, since they don't take up memory
4269     space, and not static member variables, since they don't take up memory
4270     space within an instance).
4271 
4272     Hidden fields (like the virtual function table pointer or the context
4273     pointer for nested types) are not included.
4274 
4275     For classes, only the direct member variables are included and not those
4276     of any base classes.
4277 
4278     For interfaces, the result of FieldTypes is always empty, because
4279     interfaces cannot have member variables. However, because interfaces are
4280     aggregate types, they work with FieldTypes for consistency so that code
4281     that's written to work on aggregate types doesn't have to worry about
4282     whether it's dealing with an interface.
4283 
4284     See_Also:
4285         $(LREF FieldNames)
4286         $(LREF FieldSymbols)
4287         $(DDSUBLINK spec/struct.html, struct_instance_properties, $(D tupleof))
4288   +/
4289 template FieldTypes(T)
4290 if (isAggregateType!T)
4291 {
4292     static if (is(T == struct) && __traits(isNested, T))
4293         alias FieldTypes = typeof(T.tupleof[0 .. $ - 1]);
4294     else
4295         alias FieldTypes = typeof(T.tupleof);
4296 }
4297 
4298 ///
4299 @safe unittest
4300 {
4301     import phobos.sys.meta : AliasSeq;
4302 
4303     struct S
4304     {
4305         int x;
4306         float y;
4307     }
4308     static assert(is(FieldTypes!S == AliasSeq!(int, float)));
4309 
4310     // Type qualifers will be passed on to the result.
4311     static assert(is(FieldTypes!(const S) == AliasSeq!(const int, const float)));
4312     static assert(is(FieldTypes!(shared S) == AliasSeq!(shared int, shared float)));
4313 
4314     class C
4315     {
4316         // static variables are not included.
4317         static int var;
4318 
4319         // Manifest constants are not included.
4320         enum lang = "dlang";
4321 
4322         // Functions are not included, even if they're @property functions.
4323         @property int foo() { return 42; }
4324 
4325         string s;
4326         int i;
4327         int[] arr;
4328     }
4329     static assert(is(FieldTypes!C == AliasSeq!(string, int, int[])));
4330 
4331     // Only direct member variables are included. Member variables from any base
4332     // classes are not.
4333     class D : C
4334     {
4335         real r;
4336     }
4337     static assert(is(FieldTypes!D == AliasSeq!real));
4338 
4339     // FieldTypes will always be empty for an interface, since it's not legal
4340     // for interfaces to have member variables.
4341     interface I
4342     {
4343     }
4344     static assert(FieldTypes!I.length == 0);
4345 
4346     union U
4347     {
4348         int i;
4349         double d;
4350         long l;
4351         S s;
4352     }
4353     static assert(is(FieldTypes!U == AliasSeq!(int, double, long, S)));
4354 
4355     // FieldTypes only operates on aggregate types.
4356     static assert(!__traits(compiles, FieldTypes!int));
4357     static assert(!__traits(compiles, FieldTypes!(S*)));
4358     static assert(!__traits(compiles, FieldTypes!(C[])));
4359 }
4360 
4361 @safe unittest
4362 {
4363     import phobos.sys.meta : AliasSeq;
4364 
4365     {
4366         static struct S0 {}
4367         static assert(FieldTypes!S0.length == 0);
4368 
4369         static struct S1 { int a; }
4370         static assert(is(FieldTypes!S1 == AliasSeq!int));
4371 
4372         static struct S2 { int a; string b; }
4373         static assert(is(FieldTypes!S2 == AliasSeq!(int, string)));
4374 
4375         static struct S3 { int a; string b; real c; }
4376         static assert(is(FieldTypes!S3 == AliasSeq!(int, string, real)));
4377     }
4378     {
4379         int i;
4380         struct S0 { void foo() { i = 0; }}
4381         static assert(FieldTypes!S0.length == 0);
4382         static assert(__traits(isNested, S0));
4383 
4384         struct S1 { int a; void foo() { i = 0; } }
4385         static assert(is(FieldTypes!S1 == AliasSeq!int));
4386         static assert(__traits(isNested, S1));
4387 
4388         struct S2 { int a; string b; void foo() { i = 0; } }
4389         static assert(is(FieldTypes!S2 == AliasSeq!(int, string)));
4390         static assert(__traits(isNested, S2));
4391 
4392         struct S3 { int a; string b; real c; void foo() { i = 0; } }
4393         static assert(is(FieldTypes!S3 == AliasSeq!(int, string, real)));
4394         static assert(__traits(isNested, S3));
4395     }
4396     {
4397         static class C0 {}
4398         static assert(FieldTypes!C0.length == 0);
4399 
4400         static class C1 { int a; }
4401         static assert(is(FieldTypes!C1 == AliasSeq!int));
4402 
4403         static class C2 { int a; string b; }
4404         static assert(is(FieldTypes!C2 == AliasSeq!(int, string)));
4405 
4406         static class C3 { int a; string b; real c; }
4407         static assert(is(FieldTypes!C3 == AliasSeq!(int, string, real)));
4408 
4409         static class D0 : C3 {}
4410         static assert(FieldTypes!D0.length == 0);
4411 
4412         static class D1 : C3 { bool x; }
4413         static assert(is(FieldTypes!D1 == AliasSeq!bool));
4414 
4415         static class D2 : C3 { bool x; int* y; }
4416         static assert(is(FieldTypes!D2 == AliasSeq!(bool, int*)));
4417 
4418         static class D3 : C3 { bool x; int* y; short[] z; }
4419         static assert(is(FieldTypes!D3 == AliasSeq!(bool, int*, short[])));
4420     }
4421     {
4422         int i;
4423         class C0 { void foo() { i = 0; }}
4424         static assert(FieldTypes!C0.length == 0);
4425         static assert(__traits(isNested, C0));
4426 
4427         class C1 { int a; void foo() { i = 0; } }
4428         static assert(is(FieldTypes!C1 == AliasSeq!int));
4429         static assert(__traits(isNested, C1));
4430 
4431         class C2 { int a; string b; void foo() { i = 0; } }
4432         static assert(is(FieldTypes!C2 == AliasSeq!(int, string)));
4433         static assert(__traits(isNested, C2));
4434 
4435         class C3 { int a; string b; real c; void foo() { i = 0; } }
4436         static assert(is(FieldTypes!C3 == AliasSeq!(int, string, real)));
4437         static assert(__traits(isNested, C3));
4438 
4439         class D0 : C3 {}
4440         static assert(FieldTypes!D0.length == 0);
4441         static assert(__traits(isNested, D0));
4442 
4443         class D1 : C3 { bool x; }
4444         static assert(is(FieldTypes!D1 == AliasSeq!bool));
4445         static assert(__traits(isNested, D1));
4446 
4447         class D2 : C3 { bool x; int* y; }
4448         static assert(is(FieldTypes!D2 == AliasSeq!(bool, int*)));
4449         static assert(__traits(isNested, D2));
4450 
4451         class D3 : C3 { bool x; int* y; short[] z; }
4452         static assert(is(FieldTypes!D3 == AliasSeq!(bool, int*, short[])));
4453         static assert(__traits(isNested, D3));
4454     }
4455     {
4456         static union U0 {}
4457         static assert(FieldTypes!U0.length == 0);
4458 
4459         static union U1 { int a; }
4460         static assert(is(FieldTypes!U1 == AliasSeq!int));
4461 
4462         static union U2 { int a; string b; }
4463         static assert(is(FieldTypes!U2 == AliasSeq!(int, string)));
4464 
4465         static union U3 { int a; string b; real c; }
4466         static assert(is(FieldTypes!U3 == AliasSeq!(int, string, real)));
4467     }
4468     {
4469         static struct S
4470         {
4471             enum e = 42;
4472             static str = "foobar";
4473 
4474             string name() { return "foo"; }
4475 
4476             int[] arr;
4477 
4478             struct Inner1 { int i; }
4479 
4480             static struct Inner2 { long gnol; }
4481 
4482             union { int a; string b; }
4483 
4484             alias Foo = Inner1;
4485         }
4486 
4487         static assert(is(FieldTypes!S == AliasSeq!(int[], int, string)));
4488         static assert(is(FieldTypes!(const S) == AliasSeq!(const(int[]), const int, const string)));
4489         static assert(is(FieldTypes!(S.Inner1) == AliasSeq!int));
4490         static assert(is(FieldTypes!(S.Inner2) == AliasSeq!long));
4491     }
4492 }
4493 
4494 /++
4495     Whether assigning to a variable of the given type involves either a
4496     user-defined $(D opAssign) or a compiler-generated $(D opAssign) rather than
4497     using the default assignment behavior (which would use $(D memcpy)). The
4498     $(D opAssign) must accept the same type (with compatible qualifiers) as the
4499     type which the $(D opAssign) is declared on for it to count for
4500     hasComplexAssignment.
4501 
4502     The compiler will generate an $(D opAssign) for a struct when a member
4503     variable of that struct defines an $(D opAssign). It will also generate one
4504     when the struct has a postblit constructor or destructor (and those can be
4505     either user-defined or compiler-generated).
4506 
4507     However, due to $(BUGZILLA 24834), the compiler does not currently generate
4508     an $(D opAssign) for structs that define a copy constructor, and so
4509     hasComplexAssignment is $(D false) for such types unless they have an
4510     explicit $(D opAssign), or the compiler generates one due to a member
4511     variable having an $(D opAssign).
4512 
4513     Note that hasComplexAssignment is also $(D true) for static arrays whose
4514     element type has an $(D opAssign), since while the static array itself does
4515     not have an $(D opAssign), the compiler must use the $(D opAssign) of the
4516     elements when assigning to the static array.
4517 
4518     Due to $(BUGZILLA 24833), enums never have complex assignment even if their
4519     base type does. Their $(D opAssign) is never called, resulting in incorrect
4520     behavior for such enums. So, because the compiler does not treat them as
4521     having complex assignment, hasComplexAssignment is $(D false) for them.
4522 
4523     No other types (including class references, pointers, and unions)
4524     ever have an $(D opAssign) and thus hasComplexAssignment is never $(D true)
4525     for them. It is particularly important to note that unions never have an
4526     $(D opAssign), so if a struct contains a union which contains one or more
4527     members which have an $(D opAssign), that struct will have to have a
4528     user-defined $(D opAssign) which explicitly assigns to the correct member
4529     of the union if you don't want the current value of the union to simply be
4530     memcopied when assigning to the struct.
4531 
4532     One big reason that code would need to worry about hasComplexAssignment is
4533     if void initialization is used anywhere. While it might be okay to assign
4534     to uninitialized memory for a type where assignment does a memcopy,
4535     assigning to uninitialized memory will cause serious issues with any
4536     $(D opAssign) which looks at the object before assigning to it (e.g.
4537     because the type uses reference counting). In such cases,
4538     $(REF copyEmplace, core, sys, lifetime) needs to be used instead of
4539     assignment.
4540 
4541     See_Also:
4542         $(LREF hasComplexCopying)
4543         $(LREF hasComplexDestruction)
4544         $(DDSUBLINK spec/operatoroverloading, assignment,
4545                     The language spec for overloading assignment)
4546         $(DDSUBLINK spec/struct, assign-overload,
4547                     The language spec for $(D opAssign) on structs)
4548   +/
4549 template hasComplexAssignment(T)
4550 {
4551     import core.internal.traits : hasElaborateAssign;
4552     alias hasComplexAssignment = hasElaborateAssign!T;
4553 }
4554 
4555 ///
4556 @safe unittest
4557 {
4558     static assert(!hasComplexAssignment!int);
4559     static assert(!hasComplexAssignment!real);
4560     static assert(!hasComplexAssignment!string);
4561     static assert(!hasComplexAssignment!(int[]));
4562     static assert(!hasComplexAssignment!(int[42]));
4563     static assert(!hasComplexAssignment!(int[string]));
4564     static assert(!hasComplexAssignment!Object);
4565 
4566     static struct NoOpAssign
4567     {
4568         int i;
4569     }
4570     static assert(!hasComplexAssignment!NoOpAssign);
4571 
4572     // For complex assignment, the parameter type must match the type of the
4573     // struct (with compatible qualifiers), but refness does not matter (though
4574     // it will obviously affect whether rvalues will be accepted as well as
4575     // whether non-copyable types will be accepted).
4576     static struct HasOpAssign
4577     {
4578         void opAssign(HasOpAssign) {}
4579     }
4580     static assert( hasComplexAssignment!HasOpAssign);
4581     static assert(!hasComplexAssignment!(const(HasOpAssign)));
4582 
4583     static struct HasOpAssignRef
4584     {
4585         void opAssign(ref HasOpAssignRef) {}
4586     }
4587     static assert( hasComplexAssignment!HasOpAssignRef);
4588     static assert(!hasComplexAssignment!(const(HasOpAssignRef)));
4589 
4590     static struct HasOpAssignAutoRef
4591     {
4592         void opAssign()(auto ref HasOpAssignAutoRef) {}
4593     }
4594     static assert( hasComplexAssignment!HasOpAssignAutoRef);
4595     static assert(!hasComplexAssignment!(const(HasOpAssignAutoRef)));
4596 
4597     // Assigning a mutable value works when opAssign takes const, because
4598     // mutable implicitly converts to const, but assigning to a const variable
4599     // does not work, so normally, a const object is not considered to have
4600     // complex assignment.
4601     static struct HasOpAssignC
4602     {
4603         void opAssign(const HasOpAssignC) {}
4604     }
4605     static assert( hasComplexAssignment!HasOpAssignC);
4606     static assert(!hasComplexAssignment!(const(HasOpAssignC)));
4607 
4608     // If opAssign is const, then assigning to a const variable will work, and a
4609     // const object will have complex assignment. However, such a type would
4610     // not normally make sense, since it can't actually be mutated by opAssign.
4611     static struct HasConstOpAssignC
4612     {
4613         void opAssign(const HasConstOpAssignC) const {}
4614     }
4615     static assert( hasComplexAssignment!HasConstOpAssignC);
4616     static assert( hasComplexAssignment!(const(HasConstOpAssignC)));
4617 
4618     // For a type to have complex assignment, the types must match aside from
4619     // the qualifiers. So, an opAssign which takes another type does not count
4620     // as complex assignment.
4621     static struct OtherOpAssign
4622     {
4623         void opAssign(int) {}
4624     }
4625     static assert(!hasComplexAssignment!OtherOpAssign);
4626 
4627     // The return type doesn't matter for complex assignment, though normally,
4628     // opAssign should either return a reference to the this reference (so that
4629     // assignments can be chained) or void.
4630     static struct HasOpAssignWeirdRet
4631     {
4632         int opAssign(HasOpAssignWeirdRet) { return 42; }
4633     }
4634     static assert( hasComplexAssignment!HasOpAssignWeirdRet);
4635 
4636     // The compiler will generate an assignment operator if a member variable
4637     // has one.
4638     static struct HasMemberWithOpAssign
4639     {
4640         HasOpAssign s;
4641     }
4642     static assert( hasComplexAssignment!HasMemberWithOpAssign);
4643 
4644     // The compiler will generate an assignment operator if the type has a
4645     // postblit constructor or a destructor.
4646     static struct HasDtor
4647     {
4648         ~this() {}
4649     }
4650     static assert( hasComplexAssignment!HasDtor);
4651 
4652     // If a struct has @disabled opAssign (and thus assigning to a variable of
4653     // that type will result in a compilation error), then
4654     // hasComplexAssignment is false.
4655     // Code that wants to check whether assignment works will need to test that
4656     // assigning to a variable of that type compiles (which could need to test
4657     // both an lvalue and an rvalue depending on the exact sort of assignment
4658     // the code is actually going to do).
4659     static struct DisabledOpAssign
4660     {
4661         @disable void opAssign(DisabledOpAssign);
4662     }
4663     static assert(!hasComplexAssignment!DisabledOpAssign);
4664     static assert(!__traits(compiles, { DisabledOpAssign s;
4665                                         s = rvalueOf!DisabledOpAssign;
4666                                         s = lvalueOf!DisabledOpAssign; }));
4667     static assert(!is(typeof({ DisabledOpAssign s;
4668                                s = rvalueOf!DisabledOpAssign;
4669                                s = lvalueOf!DisabledOpAssign; })));
4670 
4671     // Static arrays have complex assignment if their elements do.
4672     static assert( hasComplexAssignment!(HasOpAssign[1]));
4673 
4674     // Static arrays with no elements do not have complex assignment, because
4675     // there's nothing to assign to.
4676     static assert(!hasComplexAssignment!(HasOpAssign[0]));
4677 
4678     // Dynamic arrays do not have complex assignment, because assigning to them
4679     // just slices them rather than assigning to their elements. Assigning to
4680     // an array with a slice operation - e.g. arr[0 .. 5] = other[0 .. 5]; -
4681     // does use opAssign if the elements have it, but since assigning to the
4682     // array itself does not, hasComplexAssignment is false for dynamic arrays.
4683     static assert(!hasComplexAssignment!(HasOpAssign[]));
4684 
4685     // Classes and unions do not have complex assignment even if they have
4686     // members which do.
4687     class C
4688     {
4689         HasOpAssign s;
4690     }
4691     static assert(!hasComplexAssignment!C);
4692 
4693     union U
4694     {
4695         HasOpAssign s;
4696     }
4697     static assert(!hasComplexAssignment!U);
4698 
4699     // https://issues.dlang.org/show_bug.cgi?id=24833
4700     // This static assertion fails, because the compiler
4701     // currently ignores assignment operators for enum types.
4702     enum E : HasOpAssign { a = HasOpAssign.init }
4703     //static assert( hasComplexAssignment!E);
4704 }
4705 
4706 @safe unittest
4707 {
4708     import phobos.sys.meta : AliasSeq;
4709 
4710     {
4711         struct S1 { int i; }
4712         struct S2 { real r; }
4713         struct S3 { string s; }
4714         struct S4 { int[] arr; }
4715         struct S5 { int[0] arr; }
4716         struct S6 { int[42] arr; }
4717         struct S7 { int[string] aa; }
4718 
4719         static foreach (T; AliasSeq!(S1, S2, S3, S4, S5, S6, S7))
4720         {
4721             static assert(!hasComplexAssignment!T);
4722             static assert(!hasComplexAssignment!(T[0]));
4723             static assert(!hasComplexAssignment!(T[42]));
4724             static assert(!hasComplexAssignment!(T[]));
4725         }
4726     }
4727 
4728     // Basic variations of opAssign.
4729     {
4730         static struct S { void opAssign(S) {} }
4731         static assert( hasComplexAssignment!S);
4732 
4733         static struct S2 { S s; }
4734         static assert( hasComplexAssignment!S2);
4735     }
4736     {
4737         static struct S { void opAssign(ref S) {} }
4738         static assert( hasComplexAssignment!S);
4739 
4740         static struct S2 { S s; }
4741         static assert( hasComplexAssignment!S2);
4742     }
4743     {
4744         static struct S { void opAssign()(auto ref S) {} }
4745         static assert( hasComplexAssignment!S);
4746 
4747         static struct S2 { S s; }
4748         static assert( hasComplexAssignment!S2);
4749     }
4750     {
4751         static struct S { ref opAssign(S) { return this; } }
4752         static assert( hasComplexAssignment!S);
4753 
4754         static struct S2 { S s; }
4755         static assert( hasComplexAssignment!S2);
4756     }
4757     {
4758         static struct S { ref opAssign(ref S) { return this; } }
4759         static assert( hasComplexAssignment!S);
4760 
4761         static struct S2 { S s; }
4762         static assert( hasComplexAssignment!S2);
4763     }
4764     {
4765         static struct S { ref opAssign()(auto ref S) { return this; } }
4766         static assert( hasComplexAssignment!S);
4767 
4768         static struct S2 { S s; }
4769         static assert( hasComplexAssignment!S2);
4770     }
4771     {
4772         static struct S { ref opAssign(T)(auto ref T) { return this; } }
4773         static assert( hasComplexAssignment!S);
4774 
4775         static struct S2 { S s; }
4776         static assert( hasComplexAssignment!S2);
4777     }
4778 
4779     // Non-complex opAssign.
4780     {
4781         static struct S { ref opAssign(int) { return this; } }
4782         static assert(!hasComplexAssignment!S);
4783 
4784         static struct S2 { S s; }
4785         static assert(!hasComplexAssignment!S2);
4786     }
4787     {
4788         struct Other {}
4789         static struct S { ref opAssign(Other) { return this; } }
4790         static assert(!hasComplexAssignment!S);
4791 
4792         static struct S2 { S s; }
4793         static assert(!hasComplexAssignment!S2);
4794     }
4795 
4796     // Multiple opAssigns.
4797     {
4798         static struct S
4799         {
4800             void opAssign(S) {}
4801             void opAssign(int) {}
4802         }
4803         static assert( hasComplexAssignment!S);
4804 
4805         static struct S2 { S s; }
4806         static assert( hasComplexAssignment!S2);
4807     }
4808     {
4809         // This just flips the order of the previous test to catch potential
4810         // bugs related to the order of declaration, since that's occasionally
4811         // popped up in the compiler in other contexts.
4812         static struct S
4813         {
4814             void opAssign(int) {}
4815             void opAssign(S) {}
4816         }
4817         static assert( hasComplexAssignment!S);
4818 
4819         static struct S2 { S s; }
4820         static assert( hasComplexAssignment!S2);
4821     }
4822     {
4823         static struct S
4824         {
4825             void opAssign(S) {}
4826             void opAssign(ref S) {}
4827             void opAssign(const ref S) {}
4828         }
4829         static assert( hasComplexAssignment!S);
4830 
4831         static struct S2 { S s; }
4832         static assert( hasComplexAssignment!S2);
4833     }
4834 
4835     // Make sure that @disabled alternate opAssigns don't cause issues.
4836     {
4837         static struct S
4838         {
4839             void opAssign(S) {}
4840             @disable void opAssign(ref S) {}
4841         }
4842         static assert( hasComplexAssignment!S);
4843 
4844         // See https://issues.dlang.org/show_bug.cgi?id=24854
4845         // The compiler won't generate any opAssign (even if it theoretically
4846         // can) if the member variable has an @disabled opAssign which counts as
4847         // complex assignment.
4848         static struct S2 { S s; }
4849         static assert(!hasComplexAssignment!S2);
4850     }
4851     {
4852         static struct S
4853         {
4854             void opAssign(T)(T) {}
4855             @disable void opAssign(T)(ref T) {}
4856         }
4857         static assert( hasComplexAssignment!S);
4858 
4859         static struct S2 { S s; }
4860         static assert(!hasComplexAssignment!S2);
4861     }
4862     {
4863         static struct S
4864         {
4865             @disable void opAssign(S) {}
4866             void opAssign(ref S) {}
4867         }
4868         static assert( hasComplexAssignment!S);
4869 
4870         static struct S2 { S s; }
4871         static assert(!hasComplexAssignment!S2);
4872     }
4873     {
4874         static struct S
4875         {
4876             @disable void opAssign(T)(T) {}
4877             void opAssign(T)(ref T) {}
4878         }
4879         static assert( hasComplexAssignment!S);
4880 
4881         static struct S2 { S s; }
4882         static assert(!hasComplexAssignment!S2);
4883     }
4884     {
4885         static struct S
4886         {
4887             void opAssign(S) {}
4888             @disable void opAssign(int) {}
4889         }
4890         static assert( hasComplexAssignment!S);
4891 
4892         static struct S2 { S s; }
4893         static assert( hasComplexAssignment!S2);
4894     }
4895     {
4896         // The same as the previous test but in reverse order just to catch
4897         // compiler bugs related to the order of declaration.
4898         static struct S
4899         {
4900             @disable void opAssign(int) {}
4901             void opAssign(S) {}
4902         }
4903         static assert( hasComplexAssignment!S);
4904 
4905         static struct S2 { S s; }
4906         static assert( hasComplexAssignment!S2);
4907     }
4908 
4909     // Generated opAssign due to other functions.
4910     {
4911         static struct S { this(this) {} }
4912         static assert( hasComplexAssignment!S);
4913 
4914         static struct S2 { S s; }
4915         static assert( hasComplexAssignment!S2);
4916     }
4917     // https://issues.dlang.org/show_bug.cgi?id=24834
4918     /+
4919     {
4920         static struct S { this(ref S) {} }
4921         static assert( hasComplexAssignment!S);
4922 
4923         static struct S2 { S s; }
4924         static assert( hasComplexAssignment!S2);
4925     }
4926     +/
4927     {
4928         static struct S { ~this() {}  }
4929         static assert( hasComplexAssignment!S);
4930 
4931         static struct S2 { S s; }
4932         static assert( hasComplexAssignment!S2);
4933     }
4934 
4935     {
4936         static struct S
4937         {
4938             this(this) {}
4939             @disable void opAssign()(auto ref S) {}
4940         }
4941         static assert(!hasComplexAssignment!S);
4942 
4943         static struct S2 { S s; }
4944         static assert(!hasComplexAssignment!S2);
4945     }
4946     {
4947         static struct S
4948         {
4949             this(this) {}
4950             void opAssign()(auto ref S) {}
4951             @disable void opAssign(int) {}
4952         }
4953         static assert( hasComplexAssignment!S);
4954 
4955         static struct S2 { S s; }
4956         static assert( hasComplexAssignment!S2);
4957     }
4958 
4959     // Static arrays
4960     {
4961         static struct S { void opAssign(S) {} }
4962         static assert( hasComplexAssignment!S);
4963 
4964         static assert(!hasComplexAssignment!(S[0]));
4965         static assert( hasComplexAssignment!(S[12]));
4966         static assert(!hasComplexAssignment!(S[]));
4967 
4968         static struct S2 { S[42] s; }
4969         static assert( hasComplexAssignment!S2);
4970     }
4971 }
4972 
4973 /++
4974     Whether copying an object of the given type involves either a user-defined
4975     copy / postblit constructor or a compiler-generated copy / postblit
4976     constructor rather than using the default copying behavior (which would use
4977     $(D memcpy)).
4978 
4979     The compiler will generate a copy / postblit constructor for a struct when
4980     a member variable of that struct defines a copy / postblit constructor.
4981 
4982     Note that hasComplexCopying is also $(D true) for static arrays whose
4983     element type has a copy constructor or postblit constructor, since while
4984     the static array itself does not have a copy constructor or postblit
4985     constructor, the compiler must use the copy / postblit constructor of the
4986     elements when copying the static array.
4987 
4988     Due to $(BUGZILLA 24833), enums never have complex copying even if their
4989     base type does. Their copy / postblit constructor is never called,
4990     resulting in incorrect behavior for such enums. So, because the compiler
4991     does not treat them as having complex copying, hasComplexCopying is
4992     $(D false) for them.
4993 
4994     No other types (including class references, pointers, and unions) ever have
4995     a copy constructor or postblit constructor and thus hasComplexCopying is
4996     never $(D true) for them. It is particularly important to note that unions
4997     never have a copy constructor or postblit constructor, so if a struct
4998     contains a union which contains one or more members which have a copy
4999     constructor or postblit constructor, that struct will have to have a
5000     user-defined copy constructor or posthblit constructor which explicitly
5001     copies the correct member of the union if you don't want the current value
5002     of the union to simply be memcopied when copying the struct.
5003 
5004     If a particular piece of code cares about the existence of a copy
5005     constructor or postblit constructor specifically rather than if a type has
5006     one or the other, the traits
5007     $(DDSUBLINK spec/traits, hasCopyConstructor, $(D __traits(hasCopyConstructor, T)))
5008     and
5009     $(DDSUBLINK spec/traits, hasPostblit, $(D __traits(hasPostblit, T))) can
5010     be used, though note that they will not be true for static arrays.
5011 
5012     See_Also:
5013         $(LREF hasComplexAssignment)
5014         $(LREF hasComplexDestruction)
5015         $(DDSUBLINK spec/traits, hasCopyConstructor, $(D __traits(hasCopyConstructor, T)))
5016         $(DDSUBLINK spec/traits, hasPostblit, $(D __traits(hasPostblit, T)))
5017         $(DDSUBLINK spec/traits, isCopyable, $(D __traits(isCopyable, T)))
5018         $(DDSUBLINK spec/structs, struct-copy-constructor, The language spec for copy constructors)
5019         $(DDSUBLINK spec/structs, struct-postblit, The language spec for postblit constructors)
5020   +/
5021 template hasComplexCopying(T)
5022 {
5023     import core.internal.traits : hasElaborateCopyConstructor;
5024     alias hasComplexCopying = hasElaborateCopyConstructor!T;
5025 }
5026 
5027 ///
5028 @safe unittest
5029 {
5030     static assert(!hasComplexCopying!int);
5031     static assert(!hasComplexCopying!real);
5032     static assert(!hasComplexCopying!string);
5033     static assert(!hasComplexCopying!(int[]));
5034     static assert(!hasComplexCopying!(int[42]));
5035     static assert(!hasComplexCopying!(int[string]));
5036     static assert(!hasComplexCopying!Object);
5037 
5038     static struct NoCopyCtor1
5039     {
5040         int i;
5041     }
5042     static assert(!hasComplexCopying!NoCopyCtor1);
5043     static assert(!__traits(hasCopyConstructor, NoCopyCtor1));
5044     static assert(!__traits(hasPostblit, NoCopyCtor1));
5045 
5046     static struct NoCopyCtor2
5047     {
5048         int i;
5049 
5050         this(int i)
5051         {
5052             this.i = i;
5053         }
5054     }
5055     static assert(!hasComplexCopying!NoCopyCtor2);
5056     static assert(!__traits(hasCopyConstructor, NoCopyCtor2));
5057     static assert(!__traits(hasPostblit, NoCopyCtor2));
5058 
5059     struct HasCopyCtor
5060     {
5061         this(ref HasCopyCtor)
5062         {
5063         }
5064     }
5065     static assert( hasComplexCopying!HasCopyCtor);
5066     static assert( __traits(hasCopyConstructor, HasCopyCtor));
5067     static assert(!__traits(hasPostblit, HasCopyCtor));
5068 
5069     // hasComplexCopying does not take constness into account.
5070     // Code that wants to check whether copying works will need to test
5071     // __traits(isCopyable, T) or test that copying compiles.
5072     static assert( hasComplexCopying!(const HasCopyCtor));
5073     static assert( __traits(hasCopyConstructor, const HasCopyCtor));
5074     static assert(!__traits(hasPostblit, const HasCopyCtor));
5075     static assert(!__traits(isCopyable, const HasCopyCtor));
5076     static assert(!__traits(compiles, { const HasCopyCtor h;
5077                                         auto h2 = h; }));
5078     static assert(!is(typeof({ const HasCopyCtor h1;
5079                                auto h2 = h1; })));
5080 
5081     // An rvalue constructor is not a copy constructor.
5082     struct HasRValueCtor
5083     {
5084         this(HasRValueCtor)
5085         {
5086         }
5087     }
5088     static assert(!hasComplexCopying!HasRValueCtor);
5089     static assert(!__traits(hasCopyConstructor, HasRValueCtor));
5090     static assert(!__traits(hasPostblit, HasRValueCtor));
5091 
5092     struct HasPostblit
5093     {
5094         this(this)
5095         {
5096         }
5097     }
5098     static assert( hasComplexCopying!HasPostblit);
5099     static assert(!__traits(hasCopyConstructor, HasPostblit));
5100     static assert( __traits(hasPostblit, HasPostblit));
5101 
5102     // The compiler will generate a copy constructor if a member variable
5103     // has one.
5104     static struct HasMemberWithCopyCtor
5105     {
5106         HasCopyCtor s;
5107     }
5108     static assert( hasComplexCopying!HasMemberWithCopyCtor);
5109 
5110     // The compiler will generate a postblit constructor if a member variable
5111     // has one.
5112     static struct HasMemberWithPostblit
5113     {
5114         HasPostblit s;
5115     }
5116     static assert( hasComplexCopying!HasMemberWithPostblit);
5117 
5118     // If a struct has @disabled copying, hasComplexCopying is still true.
5119     // Code that wants to check whether copying works will need to test
5120     // __traits(isCopyable, T) or test that copying compiles.
5121     static struct DisabledCopying
5122     {
5123         @disable this(this);
5124         @disable this(ref DisabledCopying);
5125     }
5126     static assert( hasComplexCopying!DisabledCopying);
5127     static assert(!__traits(isCopyable, DisabledCopying));
5128     static assert(!__traits(compiles, { DisabledCopying dc1;
5129                                         auto dc2 = dc1; }));
5130     static assert(!is(typeof({ DisabledCopying dc1;
5131                                auto dc2 = dc1; })));
5132 
5133     // Static arrays have complex copying if their elements do.
5134     static assert( hasComplexCopying!(HasCopyCtor[1]));
5135     static assert( hasComplexCopying!(HasPostblit[1]));
5136 
5137     // Static arrays with no elements do not have complex copying, because
5138     // there's nothing to copy.
5139     static assert(!hasComplexCopying!(HasCopyCtor[0]));
5140     static assert(!hasComplexCopying!(HasPostblit[0]));
5141 
5142     // Dynamic arrays do not have complex copying, because copying them
5143     // just slices them rather than copying their elements.
5144     static assert(!hasComplexCopying!(HasCopyCtor[]));
5145     static assert(!hasComplexCopying!(HasPostblit[]));
5146 
5147     // Classes and unions do not have complex copying even if they have
5148     // members which do.
5149     class C
5150     {
5151         HasCopyCtor s;
5152     }
5153     static assert(!hasComplexCopying!C);
5154 
5155     union U
5156     {
5157         HasCopyCtor s;
5158     }
5159     static assert(!hasComplexCopying!U);
5160 
5161     // https://issues.dlang.org/show_bug.cgi?id=24833
5162     // This static assertion fails, because the compiler
5163     // currently ignores assignment operators for enum types.
5164     enum E : HasCopyCtor { a = HasCopyCtor.init }
5165     //static assert( hasComplexCopying!E);
5166 }
5167 
5168 @safe unittest
5169 {
5170     import phobos.sys.meta : AliasSeq;
5171 
5172     {
5173         struct S1 { int i; }
5174         struct S2 { real r; }
5175         struct S3 { string s; }
5176         struct S4 { int[] arr; }
5177         struct S5 { int[0] arr; }
5178         struct S6 { int[42] arr; }
5179         struct S7 { int[string] aa; }
5180 
5181         static foreach (T; AliasSeq!(S1, S2, S3, S4, S5, S6, S7))
5182         {
5183             static assert(!hasComplexCopying!T);
5184             static assert(!hasComplexCopying!(T[0]));
5185             static assert(!hasComplexCopying!(T[42]));
5186             static assert(!hasComplexCopying!(T[]));
5187         }
5188     }
5189 
5190     // Basic variations of copy constructors.
5191     {
5192         static struct S { this(ref S) {} }
5193         static assert( hasComplexCopying!S);
5194 
5195         static struct S2 { S s; }
5196         static assert( hasComplexCopying!S2);
5197     }
5198     {
5199         static struct S { this(const ref S) const {} }
5200         static assert( hasComplexCopying!S);
5201 
5202         static struct S2 { S s; }
5203         static assert( hasComplexCopying!S2);
5204     }
5205     {
5206         static struct S
5207         {
5208             this(ref S) {}
5209             this(const ref S) const {}
5210         }
5211         static assert( hasComplexCopying!S);
5212 
5213         static struct S2 { S s; }
5214         static assert( hasComplexCopying!S2);
5215     }
5216     {
5217         static struct S { this(inout ref S) inout {} }
5218         static assert( hasComplexCopying!S);
5219 
5220         static struct S2 { S s; }
5221         static assert( hasComplexCopying!S2);
5222     }
5223     {
5224         static struct S { this(scope ref S) {} }
5225         static assert( hasComplexCopying!S);
5226 
5227         static struct S2 { S s; }
5228         static assert( hasComplexCopying!S2);
5229     }
5230     {
5231         static struct S { this(scope ref S) scope {} }
5232         static assert( hasComplexCopying!S);
5233 
5234         static struct S2 { S s; }
5235         static assert( hasComplexCopying!S2);
5236     }
5237     {
5238         static struct S { this(ref S) @safe {} }
5239         static assert( hasComplexCopying!S);
5240 
5241         static struct S2 { S s; }
5242         static assert( hasComplexCopying!S2);
5243     }
5244     {
5245         static struct S { this(ref S) nothrow {} }
5246         static assert( hasComplexCopying!S);
5247 
5248         static struct S2 { S s; }
5249         static assert( hasComplexCopying!S2);
5250     }
5251     {
5252         static struct S { this(scope inout ref S) inout scope @safe pure nothrow @nogc {} }
5253         static assert( hasComplexCopying!S);
5254 
5255         static struct S2 { S s; }
5256         static assert( hasComplexCopying!S2);
5257     }
5258 
5259     // Basic variations of postblit constructors.
5260     {
5261         static struct S { this(this) {} }
5262         static assert( hasComplexCopying!S);
5263 
5264         static struct S2 { S s; }
5265         static assert( hasComplexCopying!S2);
5266     }
5267     {
5268         static struct S { this(this) scope @safe pure nothrow @nogc {} }
5269         static assert( hasComplexCopying!S);
5270 
5271         static struct S2 { S s; }
5272         static assert( hasComplexCopying!S2);
5273     }
5274 
5275     // Rvalue constructors.
5276     {
5277         static struct S { this(S) {} }
5278         static assert(!hasComplexCopying!S);
5279 
5280         static struct S2 { S s; }
5281         static assert(!hasComplexCopying!S2);
5282     }
5283     {
5284         static struct S { this(const S) const {} }
5285         static assert(!hasComplexCopying!S);
5286 
5287         static struct S2 { S s; }
5288         static assert(!hasComplexCopying!S2);
5289     }
5290     {
5291         static struct S
5292         {
5293             this(S) {}
5294             this(const S) const {}
5295         }
5296         static assert(!hasComplexCopying!S);
5297 
5298         static struct S2 { S s; }
5299         static assert(!hasComplexCopying!S2);
5300     }
5301     {
5302         static struct S { this(inout S) inout {} }
5303         static assert(!hasComplexCopying!S);
5304 
5305         static struct S2 { S s; }
5306         static assert(!hasComplexCopying!S2);
5307     }
5308     {
5309         static struct S { this(S) @safe {} }
5310         static assert(!hasComplexCopying!S);
5311 
5312         static struct S2 { S s; }
5313         static assert(!hasComplexCopying!S2);
5314     }
5315     {
5316         static struct S { this(S) nothrow {} }
5317         static assert(!hasComplexCopying!S);
5318 
5319         static struct S2 { S s; }
5320         static assert(!hasComplexCopying!S2);
5321     }
5322     {
5323         static struct S { this(inout S) inout @safe pure nothrow @nogc {} }
5324         static assert(!hasComplexCopying!S);
5325 
5326         static struct S2 { S s; }
5327         static assert(!hasComplexCopying!S2);
5328     }
5329 
5330     // @disabled copy constructors.
5331     {
5332         static struct S { @disable this(ref S) {} }
5333         static assert( hasComplexCopying!S);
5334 
5335         static struct S2 { S s; }
5336         static assert( hasComplexCopying!S2);
5337     }
5338     {
5339         static struct S { @disable this(const ref S) const {} }
5340         static assert( hasComplexCopying!S);
5341 
5342         static struct S2 { S s; }
5343         static assert( hasComplexCopying!S2);
5344     }
5345     {
5346         static struct S
5347         {
5348             @disable this(ref S) {}
5349             this(const ref S) const {}
5350         }
5351         static assert( hasComplexCopying!S);
5352 
5353         static struct S2 { S s; }
5354         static assert( hasComplexCopying!S2);
5355     }
5356     {
5357         static struct S
5358         {
5359             this(ref S) {}
5360             @disable this(const ref S) const {}
5361         }
5362         static assert( hasComplexCopying!S);
5363 
5364         static struct S2 { S s; }
5365         static assert( hasComplexCopying!S2);
5366     }
5367     {
5368         static struct S
5369         {
5370             @disable this(ref S) {}
5371             @disable this(const ref S) const {}
5372         }
5373         static assert( hasComplexCopying!S);
5374 
5375         static struct S2 { S s; }
5376         static assert( hasComplexCopying!S2);
5377     }
5378 
5379     // Static arrays
5380     {
5381         static struct S { this(ref S) {} }
5382         static assert( hasComplexCopying!S);
5383 
5384         static assert(!hasComplexCopying!(S[0]));
5385         static assert( hasComplexCopying!(S[12]));
5386         static assert(!hasComplexCopying!(S[]));
5387 
5388         static struct S2 { S[42] s; }
5389         static assert( hasComplexCopying!S2);
5390     }
5391     {
5392         static struct S { this(this) {} }
5393         static assert( hasComplexCopying!S);
5394 
5395         static assert(!hasComplexCopying!(S[0]));
5396         static assert( hasComplexCopying!(S[12]));
5397         static assert(!hasComplexCopying!(S[]));
5398 
5399         static struct S2 { S[42] s; }
5400         static assert( hasComplexCopying!S2);
5401     }
5402 }
5403 
5404 /++
5405     Whether the given type has either a user-defined destructor or a
5406     compiler-generated destructor.
5407 
5408     The compiler will generate a destructor for a struct when a member variable
5409     of that struct defines a destructor.
5410 
5411     Note that hasComplexDestruction is also $(D true) for static arrays whose
5412     element type has a destructor, since while the static array itself does not
5413     have a destructor, the compiler must use the destructor of the elements
5414     when destroying the static array.
5415 
5416     Due to $(BUGZILLA 24833), enums never have complex destruction even if their
5417     base type does. Their destructor is never called, resulting in incorrect
5418     behavior for such enums. So, because the compiler does not treat them as
5419     having complex destruction, hasComplexDestruction is $(D false) for them.
5420 
5421     Note that while the $(DDSUBLINK spec/class, destructors, language spec)
5422     currently refers to $(D ~this()) on classes as destructors (whereas the
5423     runtime refers to them as finalizers, and they're arguably finalizers
5424     rather than destructors given how they work), classes are not considered to
5425     have complex destruction. Under normal circumstances, it's just the GC or
5426     $(REF1 destroy, object) which calls the destructor / finalizer on a class
5427     (and it's not guaranteed that a class destructor / finalizer will even ever
5428     be called), which is in stark contrast to structs, which normally live on
5429     the stack and need to be destroyed when they leave scope. So,
5430     hasComplexDestruction is concerned with whether that type will have a
5431     destructor that's run when it leaves scope and not with what happens when
5432     the GC destroys an object prior to freeing its memory.
5433 
5434     No other types (including pointers and unions) ever have a destructor and
5435     thus hasComplexDestruction is never $(D true) for them. It is particularly
5436     important to note that unions never have a destructor, so if a struct
5437     contains a union which contains one or more members which have a
5438     destructor, that struct will have to have a user-defined destructor which
5439     explicitly calls $(REF1 destroy, object) on the correct member of the
5440     union if you want the object in question to be destroyed properly.
5441 
5442     See_Also:
5443         $(LREF hasComplexAssignment)
5444         $(LREF hasComplexCopying)
5445         $(REF destroy, object)
5446         $(DDSUBLINK spec/structs, struct-destructor, The language spec for destructors)
5447         $(DDSUBLINK spec/class, destructors, The language spec for class finalizers)
5448   +/
5449 template hasComplexDestruction(T)
5450 {
5451     import core.internal.traits : hasElaborateDestructor;
5452     alias hasComplexDestruction = hasElaborateDestructor!T;
5453 }
5454 
5455 ///
5456 @safe unittest
5457 {
5458     static assert(!hasComplexDestruction!int);
5459     static assert(!hasComplexDestruction!real);
5460     static assert(!hasComplexDestruction!string);
5461     static assert(!hasComplexDestruction!(int[]));
5462     static assert(!hasComplexDestruction!(int[42]));
5463     static assert(!hasComplexDestruction!(int[string]));
5464     static assert(!hasComplexDestruction!Object);
5465 
5466     static struct NoDtor
5467     {
5468         int i;
5469     }
5470     static assert(!hasComplexDestruction!NoDtor);
5471 
5472     struct HasDtor
5473     {
5474         ~this() {}
5475     }
5476     static assert( hasComplexDestruction!HasDtor);
5477 
5478     // The compiler will generate a destructor if a member variable has one.
5479     static struct HasMemberWithDtor
5480     {
5481         HasDtor s;
5482     }
5483     static assert( hasComplexDestruction!HasMemberWithDtor);
5484 
5485     // If a struct has @disabled destruction, hasComplexDestruction is still
5486     // true. Code that wants to check whether destruction works can either
5487     // test for whether the __xdtor member is disabled, or it can test whether
5488     // code that will destroy the object compiles. That being said, a disabled
5489     // destructor probably isn't very common in practice, because about all that
5490     // such a type is good for is being allocated on the heap.
5491     static struct DisabledDtor
5492     {
5493         @disable ~this() {}
5494     }
5495     static assert( hasComplexDestruction!DisabledDtor);
5496     static assert( __traits(isDisabled,
5497                             __traits(getMember, DisabledDtor, "__xdtor")));
5498 
5499     // A type with a disabled destructor cannot be created on the stack or used
5500     // in any way that would ever trigger a destructor, making it pretty much
5501     // useless outside of providing a way to force a struct to be allocated on
5502     // the heap - though that could be useful in some situations, since it
5503     // it makes it possible to have a type that has to be a reference type but
5504     // which doesn't have the overhead of a class.
5505     static assert(!__traits(compiles, { DisabledDtor d; }));
5506     static assert( __traits(compiles, { auto d = new DisabledDtor; }));
5507 
5508     // Static arrays have complex destruction if their elements do.
5509     static assert( hasComplexDestruction!(HasDtor[1]));
5510 
5511     // Static arrays with no elements do not have complex destruction, because
5512     // there's nothing to destroy.
5513     static assert(!hasComplexDestruction!(HasDtor[0]));
5514 
5515     // Dynamic arrays do not have complex destruction, because their elements
5516     // are contained in the memory that the dynamic array is a slice of and not
5517     // in the dynamic array itself, so there's nothing to destroy when a
5518     // dynamic array leaves scope.
5519     static assert(!hasComplexDestruction!(HasDtor[]));
5520 
5521     // Classes and unions do not have complex copying even if they have
5522     // members which do.
5523     class C
5524     {
5525         HasDtor s;
5526     }
5527     static assert(!hasComplexDestruction!C);
5528 
5529     union U
5530     {
5531         HasDtor s;
5532     }
5533     static assert(!hasComplexDestruction!U);
5534 
5535     // https://issues.dlang.org/show_bug.cgi?id=24833
5536     // This static assertion fails, because the compiler
5537     // currently ignores assignment operators for enum types.
5538     enum E : HasDtor { a = HasDtor.init }
5539     //static assert( hasComplexDestruction!E);
5540 }
5541 
5542 @safe unittest
5543 {
5544     import phobos.sys.meta : AliasSeq;
5545 
5546     {
5547         struct S1 { int i; }
5548         struct S2 { real r; }
5549         struct S3 { string s; }
5550         struct S4 { int[] arr; }
5551         struct S5 { int[0] arr; }
5552         struct S6 { int[42] arr; }
5553         struct S7 { int[string] aa; }
5554 
5555         static foreach (T; AliasSeq!(S1, S2, S3, S4, S5, S6, S7))
5556         {
5557             static assert(!hasComplexDestruction!T);
5558             static assert(!hasComplexDestruction!(T[0]));
5559             static assert(!hasComplexDestruction!(T[42]));
5560             static assert(!hasComplexDestruction!(T[]));
5561         }
5562     }
5563 
5564     // Basic variations of destructors.
5565     {
5566         static struct S { ~this() {} }
5567         static assert( hasComplexDestruction!S);
5568 
5569         static struct S2 { S s; }
5570         static assert( hasComplexDestruction!S2);
5571     }
5572     {
5573         static struct S { ~this() const {} }
5574         static assert( hasComplexDestruction!S);
5575 
5576         static struct S2 { S s; }
5577         static assert( hasComplexDestruction!S2);
5578     }
5579     {
5580         static struct S { ~this() @safe {} }
5581         static assert( hasComplexDestruction!S);
5582 
5583         static struct S2 { S s; }
5584         static assert( hasComplexDestruction!S2);
5585     }
5586     {
5587         static struct S { ~this() @safe pure nothrow @nogc {} }
5588         static assert( hasComplexDestruction!S);
5589 
5590         static struct S2 { S s; }
5591         static assert( hasComplexDestruction!S2);
5592     }
5593 
5594     // @disabled destructors.
5595     {
5596         static struct S { @disable ~this() {} }
5597         static assert( __traits(isDisabled,
5598                                 __traits(getMember, S, "__xdtor")));
5599 
5600         static struct S2 { S s; }
5601         static assert( hasComplexDestruction!S2);
5602         static assert( __traits(isDisabled,
5603                                 __traits(getMember, S2, "__xdtor")));
5604     }
5605 
5606     // Static arrays
5607     {
5608         static struct S { ~this() {} }
5609         static assert( hasComplexDestruction!S);
5610 
5611         static assert(!hasComplexDestruction!(S[0]));
5612         static assert( hasComplexDestruction!(S[12]));
5613         static assert(!hasComplexDestruction!(S[]));
5614 
5615         static struct S2 { S[42] s; }
5616         static assert( hasComplexDestruction!S2);
5617     }
5618 }
5619 
5620 /++
5621     Evaluates to $(D true) if the given type is one or more of the following,
5622     or if it's a struct, union, or static array which contains one or more of
5623     the following:
5624 
5625     $(OL $(LI A raw pointer)
5626          $(LI A class reference)
5627          $(LI An interface reference)
5628          $(LI A dynamic array)
5629          $(LI An associative array)
5630          $(LI A delegate)
5631          $(LI A struct with a
5632               $(DDSUBLINK spec/traits, isNested, $(D context pointer)).))
5633 
5634     Note that function pointers are not considered to have indirections, because
5635     they do not point to any data (whereas a delegate has a context pointer
5636     and therefore has data that it points to).
5637 
5638     Also, while static arrays do not have indirections unless their element
5639     type has indirections, static arrays with an element type of $(D void) are
5640     considered to have indirections by hasIndirections, because it's unknown
5641     what type their elements actually are, so they $(I might) have
5642     indirections, and thus, the conservative approach is to assume that they do
5643     have indirections.
5644 
5645     Static arrays with length 0 do not have indirections no matter what their
5646     element type is, since they don't actually have any elements.
5647   +/
5648 version (StdDdoc) template hasIndirections(T)
5649 {
5650     import core.internal.traits : _hasIndirections = hasIndirections;
5651     alias hasIndirections = _hasIndirections!T;
5652 }
5653 else
5654 {
5655     import core.internal.traits : _hasIndirections = hasIndirections;
5656     alias hasIndirections = _hasIndirections;
5657 }
5658 
5659 ///
5660 @safe unittest
5661 {
5662     static class C {}
5663     static interface I {}
5664 
5665     static assert( hasIndirections!(int*));
5666     static assert( hasIndirections!C);
5667     static assert( hasIndirections!I);
5668     static assert( hasIndirections!(int[]));
5669     static assert( hasIndirections!(int[string]));
5670     static assert( hasIndirections!(void delegate()));
5671     static assert( hasIndirections!(string delegate(int)));
5672 
5673     static assert(!hasIndirections!(void function()));
5674     static assert(!hasIndirections!int);
5675 
5676     static assert(!hasIndirections!(ubyte[9]));
5677     static assert( hasIndirections!(ubyte[9]*));
5678     static assert( hasIndirections!(ubyte*[9]));
5679     static assert(!hasIndirections!(ubyte*[0]));
5680     static assert( hasIndirections!(ubyte[]));
5681 
5682     static assert( hasIndirections!(void[]));
5683     static assert( hasIndirections!(void[42]));
5684 
5685     static struct NoContext
5686     {
5687         int i;
5688     }
5689 
5690     int local;
5691 
5692     struct HasContext
5693     {
5694         int foo() { return local; }
5695     }
5696 
5697     struct HasMembersWithIndirections
5698     {
5699         int* ptr;
5700     }
5701 
5702     static assert(!hasIndirections!NoContext);
5703     static assert( hasIndirections!HasContext);
5704     static assert( hasIndirections!HasMembersWithIndirections);
5705 
5706     union U1
5707     {
5708         int i;
5709         float f;
5710     }
5711     static assert(!hasIndirections!U1);
5712 
5713     union U2
5714     {
5715         int i;
5716         int[] arr;
5717     }
5718     static assert( hasIndirections!U2);
5719 }
5720 
5721 // hasIndirections with types which aren't aggregate types.
5722 @safe unittest
5723 {
5724     import phobos.sys.meta : AliasSeq;
5725 
5726     alias testWithQualifiers = assertWithQualifiers!hasIndirections;
5727 
5728     foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
5729                           float, double, real, char, wchar, dchar, int function(string), void))
5730     {
5731         mixin testWithQualifiers!(T, false);
5732         mixin testWithQualifiers!(T*, true);
5733         mixin testWithQualifiers!(T[], true);
5734 
5735         mixin testWithQualifiers!(T[42], is(T == void));
5736         mixin testWithQualifiers!(T[0], false);
5737 
5738         mixin testWithQualifiers!(T*[42], true);
5739         mixin testWithQualifiers!(T*[0], false);
5740 
5741         mixin testWithQualifiers!(T[][42], true);
5742         mixin testWithQualifiers!(T[][0], false);
5743     }
5744 
5745     foreach (T; AliasSeq!(int[int], int delegate(string)))
5746     {
5747         mixin testWithQualifiers!(T, true);
5748         mixin testWithQualifiers!(T*, true);
5749         mixin testWithQualifiers!(T[], true);
5750 
5751         mixin testWithQualifiers!(T[42], true);
5752         mixin testWithQualifiers!(T[0], false);
5753 
5754         mixin testWithQualifiers!(T*[42], true);
5755         mixin testWithQualifiers!(T*[0], false);
5756 
5757         mixin testWithQualifiers!(T[][42], true);
5758         mixin testWithQualifiers!(T[][0], false);
5759     }
5760 }
5761 
5762 // hasIndirections with structs.
5763 @safe unittest
5764 {
5765     import phobos.sys.meta : AliasSeq;
5766 
5767     alias testWithQualifiers = assertWithQualifiers!hasIndirections;
5768 
5769     {
5770         struct S {}
5771         mixin testWithQualifiers!(S, false);
5772     }
5773     {
5774         static struct S {}
5775         mixin testWithQualifiers!(S, false);
5776     }
5777     {
5778         struct S { void foo() {} }
5779         mixin testWithQualifiers!(S, true);
5780     }
5781     {
5782         static struct S { void foo() {} }
5783         mixin testWithQualifiers!(S, false);
5784     }
5785 
5786     // Structs with members which aren't aggregate types and don't have indirections.
5787     foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
5788                           float, double, real, char, wchar, dchar, int function(string)))
5789     {
5790         // No indirections.
5791         {
5792             struct S { T member; }
5793             mixin testWithQualifiers!(S, false);
5794         }
5795         {
5796             struct S { const T member; }
5797             mixin testWithQualifiers!(S, false);
5798         }
5799         {
5800             struct S { immutable T member; }
5801             mixin testWithQualifiers!(S, false);
5802         }
5803         {
5804             struct S { shared T member; }
5805             mixin testWithQualifiers!(S, false);
5806         }
5807 
5808         {
5809             static struct S { T member; void foo() {} }
5810             mixin testWithQualifiers!(S, false);
5811         }
5812         {
5813             static struct S { const T member; void foo() {} }
5814             mixin testWithQualifiers!(S, false);
5815         }
5816         {
5817             static struct S { immutable T member; void foo() {} }
5818             mixin testWithQualifiers!(S, false);
5819         }
5820         {
5821             static struct S { shared T member; void foo() {} }
5822             mixin testWithQualifiers!(S, false);
5823         }
5824 
5825         // Has context pointer.
5826         {
5827             struct S { T member; void foo() {} }
5828             mixin testWithQualifiers!(S, true);
5829         }
5830         {
5831             struct S { const T member; void foo() {} }
5832             mixin testWithQualifiers!(S, true);
5833         }
5834         {
5835             struct S { immutable T member; void foo() {} }
5836             mixin testWithQualifiers!(S, true);
5837         }
5838         {
5839             struct S { shared T member; void foo() {} }
5840             mixin testWithQualifiers!(S, true);
5841         }
5842 
5843         {
5844             T local;
5845             struct S { void foo() { auto v = local; } }
5846             mixin testWithQualifiers!(S, true);
5847         }
5848         {
5849             const T local;
5850             struct S { void foo() { auto v = local; } }
5851             mixin testWithQualifiers!(S, true);
5852         }
5853         {
5854             immutable T local;
5855             struct S { void foo() { auto v = local; } }
5856             mixin testWithQualifiers!(S, true);
5857         }
5858         {
5859             shared T local;
5860             struct S { void foo() @trusted { auto v = cast() local; } }
5861             mixin testWithQualifiers!(S, true);
5862         }
5863 
5864         // Pointers.
5865         {
5866             struct S { T* member; }
5867             mixin testWithQualifiers!(S, true);
5868         }
5869         {
5870             struct S { const(T)* member; }
5871             mixin testWithQualifiers!(S, true);
5872         }
5873         {
5874             struct S { const T* member; }
5875             mixin testWithQualifiers!(S, true);
5876         }
5877         {
5878             struct S { immutable T* member; }
5879             mixin testWithQualifiers!(S, true);
5880         }
5881         {
5882             struct S { shared T* member; }
5883             mixin testWithQualifiers!(S, true);
5884         }
5885 
5886         // Dynamic arrays.
5887         {
5888             struct S { T[] member; }
5889             mixin testWithQualifiers!(S, true);
5890         }
5891         {
5892             struct S { const(T)[] member; }
5893             mixin testWithQualifiers!(S, true);
5894         }
5895         {
5896             struct S { const T[] member; }
5897             mixin testWithQualifiers!(S, true);
5898         }
5899         {
5900             struct S { immutable T[] member; }
5901             mixin testWithQualifiers!(S, true);
5902         }
5903         {
5904             struct S { shared T[] member; }
5905             mixin testWithQualifiers!(S, true);
5906         }
5907 
5908         // Static arrays.
5909         {
5910             struct S { T[1] member; }
5911             mixin testWithQualifiers!(S, false);
5912         }
5913         {
5914             struct S { const(T)[1] member; }
5915             mixin testWithQualifiers!(S, false);
5916         }
5917         {
5918             struct S { const T[1] member; }
5919             mixin testWithQualifiers!(S, false);
5920         }
5921         {
5922             struct S { immutable T[1] member; }
5923             mixin testWithQualifiers!(S, false);
5924         }
5925         {
5926             struct S { shared T[1] member; }
5927             mixin testWithQualifiers!(S, false);
5928         }
5929 
5930         // Static arrays of pointers.
5931         {
5932             struct S { T*[1] member; }
5933             mixin testWithQualifiers!(S, true);
5934         }
5935         {
5936             struct S { const(T)*[1] member; }
5937             mixin testWithQualifiers!(S, true);
5938         }
5939         {
5940             struct S { const(T*)[1] member; }
5941             mixin testWithQualifiers!(S, true);
5942         }
5943         {
5944             struct S { const T*[1] member; }
5945             mixin testWithQualifiers!(S, true);
5946         }
5947         {
5948             struct S { immutable T*[1] member; }
5949             mixin testWithQualifiers!(S, true);
5950         }
5951         {
5952             struct S { shared T*[1] member; }
5953             mixin testWithQualifiers!(S, true);
5954         }
5955 
5956         {
5957             struct S { T*[0] member; }
5958             mixin testWithQualifiers!(S, false);
5959         }
5960         {
5961             struct S { const(T)*[0] member; }
5962             mixin testWithQualifiers!(S, false);
5963         }
5964         {
5965             struct S { const(T*)[0] member; }
5966             mixin testWithQualifiers!(S, false);
5967         }
5968         {
5969             struct S { const T*[0] member; }
5970             mixin testWithQualifiers!(S, false);
5971         }
5972         {
5973             struct S { immutable T*[0] member; }
5974             mixin testWithQualifiers!(S, false);
5975         }
5976         {
5977             struct S { shared T*[0] member; }
5978             mixin testWithQualifiers!(S, false);
5979         }
5980 
5981         // Static arrays of dynamic arrays.
5982         {
5983             struct S { T[][1] member; }
5984             mixin testWithQualifiers!(S, true);
5985         }
5986         {
5987             struct S { const(T)[][1] member; }
5988             mixin testWithQualifiers!(S, true);
5989         }
5990         {
5991             struct S { const(T[])[1] member; }
5992             mixin testWithQualifiers!(S, true);
5993         }
5994         {
5995             struct S { const T[][1] member; }
5996             mixin testWithQualifiers!(S, true);
5997         }
5998         {
5999             struct S { immutable T[][1] member; }
6000             mixin testWithQualifiers!(S, true);
6001         }
6002         {
6003             struct S { shared T[][1] member; }
6004             mixin testWithQualifiers!(S, true);
6005         }
6006 
6007         {
6008             struct S { T[][0] member; }
6009             mixin testWithQualifiers!(S, false);
6010         }
6011         {
6012             struct S { const(T)[][0] member; }
6013             mixin testWithQualifiers!(S, false);
6014         }
6015         {
6016             struct S { const(T[])[0] member; }
6017             mixin testWithQualifiers!(S, false);
6018         }
6019         {
6020             struct S { const T[][0] member; }
6021             mixin testWithQualifiers!(S, false);
6022         }
6023         {
6024             struct S { immutable T[][0] member; }
6025             mixin testWithQualifiers!(S, false);
6026         }
6027         {
6028             struct S { shared T[][0] member; }
6029             mixin testWithQualifiers!(S, false);
6030         }
6031     }
6032 
6033     // Structs with arrays of void.
6034     {
6035         {
6036             static struct S { void[] member; }
6037             mixin testWithQualifiers!(S, true);
6038         }
6039         {
6040             static struct S { void[1] member; }
6041             mixin testWithQualifiers!(S, true);
6042         }
6043         {
6044             static struct S { void[0] member; }
6045             mixin testWithQualifiers!(S, false);
6046         }
6047     }
6048 
6049     // Structs with multiple members, testing pointer types.
6050     {
6051         static struct S { int i; bool b; }
6052         mixin testWithQualifiers!(S, false);
6053     }
6054     {
6055         static struct S { int* i; bool b; }
6056         mixin testWithQualifiers!(S, true);
6057     }
6058     {
6059         static struct S { int i; bool* b; }
6060         mixin testWithQualifiers!(S, true);
6061     }
6062     {
6063         static struct S { int* i; bool* b; }
6064         mixin testWithQualifiers!(S, true);
6065     }
6066 
6067     // Structs with multiple members, testing dynamic arrays.
6068     {
6069         static struct S { int[] arr; }
6070         mixin testWithQualifiers!(S, true);
6071     }
6072     {
6073         static struct S { int i; int[] arr; }
6074         mixin testWithQualifiers!(S, true);
6075     }
6076     {
6077         static struct S { int[] arr; int i; }
6078         mixin testWithQualifiers!(S, true);
6079     }
6080 
6081     // Structs with multiple members, testing static arrays.
6082     {
6083         static struct S { int[1] arr; }
6084         mixin testWithQualifiers!(S, false);
6085     }
6086     {
6087         static struct S { int i; int[1] arr; }
6088         mixin testWithQualifiers!(S, false);
6089     }
6090     {
6091         static struct S { int[1] arr; int i; }
6092         mixin testWithQualifiers!(S, false);
6093     }
6094 
6095     {
6096         static struct S { int*[0] arr; }
6097         mixin testWithQualifiers!(S, false);
6098     }
6099     {
6100         static struct S { int i; int*[0] arr; }
6101         mixin testWithQualifiers!(S, false);
6102     }
6103     {
6104         static struct S { int*[0] arr; int i; }
6105         mixin testWithQualifiers!(S, false);
6106     }
6107 
6108     {
6109         static struct S { string[42] arr; }
6110         mixin testWithQualifiers!(S, true);
6111     }
6112     {
6113         static struct S { int i; string[42] arr; }
6114         mixin testWithQualifiers!(S, true);
6115     }
6116     {
6117         static struct S { string[42] arr; int i; }
6118         mixin testWithQualifiers!(S, true);
6119     }
6120 
6121     // Structs with associative arrays.
6122     {
6123         static struct S { int[string] aa; }
6124         mixin testWithQualifiers!(S, true);
6125     }
6126     {
6127         static struct S { int i; int[string] aa; }
6128         mixin testWithQualifiers!(S, true);
6129     }
6130     {
6131         static struct S { int[string] aa; int i; }
6132         mixin testWithQualifiers!(S, true);
6133     }
6134 
6135     {
6136         static struct S { int[42][int] aa; }
6137         mixin testWithQualifiers!(S, true);
6138     }
6139     {
6140         static struct S { int[0][int] aa; }
6141         mixin testWithQualifiers!(S, true);
6142     }
6143 
6144     // Structs with classes.
6145     {
6146         class C {}
6147         struct S { C c; }
6148         mixin testWithQualifiers!(S, true);
6149     }
6150     {
6151         interface I {}
6152         struct S { I i; }
6153         mixin testWithQualifiers!(S, true);
6154     }
6155 
6156     // Structs with delegates.
6157     {
6158         struct S { void delegate() d; }
6159         mixin testWithQualifiers!(S, true);
6160     }
6161     {
6162         struct S { int delegate(int) d; }
6163         mixin testWithQualifiers!(S, true);
6164     }
6165 
6166     // Structs multiple layers deep.
6167     {
6168         struct S1 { int i; }
6169         struct S2 { S1 s; }
6170         struct S3 { S2 s; }
6171         struct S4 { S3 s; }
6172         struct S5 { S4 s; }
6173         struct S6 { S5 s; }
6174         struct S7 { S6[0] s; }
6175         struct S8 { S7 s; }
6176         struct S9 { S8 s; }
6177         struct S10 { S9 s; }
6178         mixin testWithQualifiers!(S1, false);
6179         mixin testWithQualifiers!(S2, false);
6180         mixin testWithQualifiers!(S3, false);
6181         mixin testWithQualifiers!(S4, false);
6182         mixin testWithQualifiers!(S5, false);
6183         mixin testWithQualifiers!(S6, false);
6184         mixin testWithQualifiers!(S7, false);
6185         mixin testWithQualifiers!(S8, false);
6186         mixin testWithQualifiers!(S9, false);
6187         mixin testWithQualifiers!(S10, false);
6188     }
6189     {
6190         struct S1 { int* i; }
6191         struct S2 { S1 s; }
6192         struct S3 { S2 s; }
6193         struct S4 { S3 s; }
6194         struct S5 { S4 s; }
6195         struct S6 { S5 s; }
6196         struct S7 { S6[0] s; }
6197         struct S8 { S7 s; }
6198         struct S9 { S8 s; }
6199         struct S10 { S9 s; }
6200         mixin testWithQualifiers!(S1, true);
6201         mixin testWithQualifiers!(S2, true);
6202         mixin testWithQualifiers!(S3, true);
6203         mixin testWithQualifiers!(S4, true);
6204         mixin testWithQualifiers!(S5, true);
6205         mixin testWithQualifiers!(S6, true);
6206         mixin testWithQualifiers!(S7, false);
6207         mixin testWithQualifiers!(S8, false);
6208         mixin testWithQualifiers!(S9, false);
6209         mixin testWithQualifiers!(S10, false);
6210     }
6211 }
6212 
6213 // hasIndirections with unions.
6214 @safe unittest
6215 {
6216     import phobos.sys.meta : AliasSeq;
6217 
6218     alias testWithQualifiers = assertWithQualifiers!hasIndirections;
6219 
6220     {
6221         union U {}
6222         mixin testWithQualifiers!(U, false);
6223     }
6224     {
6225         static union U {}
6226         mixin testWithQualifiers!(U, false);
6227     }
6228 
6229     // Unions with members which aren't aggregate types and don't have indirections.
6230     foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
6231                           float, double, real, char, wchar, dchar, int function(string)))
6232     {
6233         // No indirections.
6234         {
6235             union U { T member; }
6236             mixin testWithQualifiers!(U, false);
6237         }
6238         {
6239             union U { const T member; }
6240             mixin testWithQualifiers!(U, false);
6241         }
6242         {
6243             union U { immutable T member; }
6244             mixin testWithQualifiers!(U, false);
6245         }
6246         {
6247             union U { shared T member; }
6248             mixin testWithQualifiers!(U, false);
6249         }
6250 
6251         // Pointers.
6252         {
6253             union U { T* member; }
6254             mixin testWithQualifiers!(U, true);
6255         }
6256         {
6257             union U { const(T)* member; }
6258             mixin testWithQualifiers!(U, true);
6259         }
6260         {
6261             union U { const T* member; }
6262             mixin testWithQualifiers!(U, true);
6263         }
6264         {
6265             union U { immutable T* member; }
6266             mixin testWithQualifiers!(U, true);
6267         }
6268         {
6269             union U { shared T* member; }
6270             mixin testWithQualifiers!(U, true);
6271         }
6272 
6273         // Dynamic arrays.
6274         {
6275             union U { T[] member; }
6276             mixin testWithQualifiers!(U, true);
6277         }
6278         {
6279             union U { const(T)[] member; }
6280             mixin testWithQualifiers!(U, true);
6281         }
6282         {
6283             union U { const T[] member; }
6284             mixin testWithQualifiers!(U, true);
6285         }
6286         {
6287             union U { immutable T[] member; }
6288             mixin testWithQualifiers!(U, true);
6289         }
6290         {
6291             union U { shared T[] member; }
6292             mixin testWithQualifiers!(U, true);
6293         }
6294 
6295         // Static arrays.
6296         {
6297             union U { T[1] member; }
6298             mixin testWithQualifiers!(U, false);
6299         }
6300         {
6301             union U { const(T)[1] member; }
6302             mixin testWithQualifiers!(U, false);
6303         }
6304         {
6305             union U { const T[1] member; }
6306             mixin testWithQualifiers!(U, false);
6307         }
6308         {
6309             union U { immutable T[1] member; }
6310             mixin testWithQualifiers!(U, false);
6311         }
6312         {
6313             union U { shared T[1] member; }
6314             mixin testWithQualifiers!(U, false);
6315         }
6316 
6317         // Static arrays of pointers.
6318         {
6319             union U { T*[1] member; }
6320             mixin testWithQualifiers!(U, true);
6321         }
6322         {
6323             union U { const(T)*[1] member; }
6324             mixin testWithQualifiers!(U, true);
6325         }
6326         {
6327             union U { const(T*)[1] member; }
6328             mixin testWithQualifiers!(U, true);
6329         }
6330         {
6331             union U { const T*[1] member; }
6332             mixin testWithQualifiers!(U, true);
6333         }
6334         {
6335             union U { immutable T*[1] member; }
6336             mixin testWithQualifiers!(U, true);
6337         }
6338         {
6339             union U { shared T*[1] member; }
6340             mixin testWithQualifiers!(U, true);
6341         }
6342 
6343         {
6344             union U { T*[0] member; }
6345             mixin testWithQualifiers!(U, false);
6346         }
6347         {
6348             union U { const(T)*[0] member; }
6349             mixin testWithQualifiers!(U, false);
6350         }
6351         {
6352             union U { const(T*)[0] member; }
6353             mixin testWithQualifiers!(U, false);
6354         }
6355         {
6356             union U { const T*[0] member; }
6357             mixin testWithQualifiers!(U, false);
6358         }
6359         {
6360             union U { immutable T*[0] member; }
6361             mixin testWithQualifiers!(U, false);
6362         }
6363         {
6364             union U { shared T*[0] member; }
6365             mixin testWithQualifiers!(U, false);
6366         }
6367 
6368         // Static arrays of dynamic arrays.
6369         {
6370             union U { T[][1] member; }
6371             mixin testWithQualifiers!(U, true);
6372         }
6373         {
6374             union U { const(T)[][1] member; }
6375             mixin testWithQualifiers!(U, true);
6376         }
6377         {
6378             union U { const(T[])[1] member; }
6379             mixin testWithQualifiers!(U, true);
6380         }
6381         {
6382             union U { const T[][1] member; }
6383             mixin testWithQualifiers!(U, true);
6384         }
6385         {
6386             union U { immutable T[][1] member; }
6387             mixin testWithQualifiers!(U, true);
6388         }
6389         {
6390             union U { shared T[][1] member; }
6391             mixin testWithQualifiers!(U, true);
6392         }
6393 
6394         {
6395             union U { T[][0] member; }
6396             mixin testWithQualifiers!(U, false);
6397         }
6398         {
6399             union U { const(T)[][0] member; }
6400             mixin testWithQualifiers!(U, false);
6401         }
6402         {
6403             union U { const(T[])[0] member; }
6404             mixin testWithQualifiers!(U, false);
6405         }
6406         {
6407             union U { const T[][0] member; }
6408             mixin testWithQualifiers!(U, false);
6409         }
6410         {
6411             union U { immutable T[][0] member; }
6412             mixin testWithQualifiers!(U, false);
6413         }
6414         {
6415             union U { shared T[][0] member; }
6416             mixin testWithQualifiers!(U, false);
6417         }
6418     }
6419 
6420     // Unions with arrays of void.
6421     {
6422         {
6423             static union U { void[] member; }
6424             mixin testWithQualifiers!(U, true);
6425         }
6426         {
6427             static union U { void[1] member; }
6428             mixin testWithQualifiers!(U, true);
6429         }
6430         {
6431             static union U { void[0] member; }
6432             mixin testWithQualifiers!(U, false);
6433         }
6434     }
6435 
6436     // Unions with multiple members, testing pointer types.
6437     {
6438         static union U { int i; bool b; }
6439         mixin testWithQualifiers!(U, false);
6440     }
6441     {
6442         static union U { int* i; bool b; }
6443         mixin testWithQualifiers!(U, true);
6444     }
6445     {
6446         static union U { int i; bool* b; }
6447         mixin testWithQualifiers!(U, true);
6448     }
6449     {
6450         static union U { int* i; bool* b; }
6451         mixin testWithQualifiers!(U, true);
6452     }
6453 
6454     // Unions with multiple members, testing dynamic arrays.
6455     {
6456         static union U { int[] arr; }
6457         mixin testWithQualifiers!(U, true);
6458     }
6459     {
6460         static union U { int i; int[] arr; }
6461         mixin testWithQualifiers!(U, true);
6462     }
6463     {
6464         static union U { int[] arr; int i; }
6465         mixin testWithQualifiers!(U, true);
6466     }
6467 
6468     // Unions with multiple members, testing static arrays.
6469     {
6470         static union U { int[1] arr; }
6471         mixin testWithQualifiers!(U, false);
6472     }
6473     {
6474         static union U { int i; int[1] arr; }
6475         mixin testWithQualifiers!(U, false);
6476     }
6477     {
6478         static union U { int[1] arr; int i; }
6479         mixin testWithQualifiers!(U, false);
6480     }
6481 
6482     {
6483         static union U { int*[0] arr; }
6484         mixin testWithQualifiers!(U, false);
6485     }
6486     {
6487         static union U { int i; int*[0] arr; }
6488         mixin testWithQualifiers!(U, false);
6489     }
6490     {
6491         static union U { int*[0] arr; int i; }
6492         mixin testWithQualifiers!(U, false);
6493     }
6494 
6495     {
6496         static union U { string[42] arr; }
6497         mixin testWithQualifiers!(U, true);
6498     }
6499     {
6500         static union U { int i; string[42] arr; }
6501         mixin testWithQualifiers!(U, true);
6502     }
6503     {
6504         static union U { string[42] arr; int i; }
6505         mixin testWithQualifiers!(U, true);
6506     }
6507 
6508     // Unions with associative arrays.
6509     {
6510         static union U { int[string] aa; }
6511         mixin testWithQualifiers!(U, true);
6512     }
6513     {
6514         static union U { int i; int[string] aa; }
6515         mixin testWithQualifiers!(U, true);
6516     }
6517     {
6518         static union U { int[string] aa; int i; }
6519         mixin testWithQualifiers!(U, true);
6520     }
6521 
6522     {
6523         static union U { int[42][int] aa; }
6524         mixin testWithQualifiers!(U, true);
6525     }
6526     {
6527         static union U { int[0][int] aa; }
6528         mixin testWithQualifiers!(U, true);
6529     }
6530 
6531     // Unions with classes.
6532     {
6533         class C {}
6534         union U { C c; }
6535         mixin testWithQualifiers!(U, true);
6536     }
6537     {
6538         interface I {}
6539         union U { I i; }
6540         mixin testWithQualifiers!(U, true);
6541     }
6542 
6543     // Unions with delegates.
6544     {
6545         union U { void delegate() d; }
6546         mixin testWithQualifiers!(U, true);
6547     }
6548     {
6549         union U { int delegate(int) d; }
6550         mixin testWithQualifiers!(U, true);
6551     }
6552 
6553     // Unions multiple layers deep.
6554     {
6555         union U1 { int i; }
6556         union U2 { U1 s; }
6557         union U3 { U2 s; }
6558         union U4 { U3 s; }
6559         union U5 { U4 s; }
6560         union U6 { U5 s; }
6561         union U7 { U6[0] s; }
6562         union U8 { U7 s; }
6563         union U9 { U8 s; }
6564         union U10 { U9 s; }
6565         mixin testWithQualifiers!(U1, false);
6566         mixin testWithQualifiers!(U2, false);
6567         mixin testWithQualifiers!(U3, false);
6568         mixin testWithQualifiers!(U4, false);
6569         mixin testWithQualifiers!(U5, false);
6570         mixin testWithQualifiers!(U6, false);
6571         mixin testWithQualifiers!(U7, false);
6572         mixin testWithQualifiers!(U8, false);
6573         mixin testWithQualifiers!(U9, false);
6574         mixin testWithQualifiers!(U10, false);
6575     }
6576     {
6577         union U1 { int* i; }
6578         union U2 { U1 s; }
6579         union U3 { U2 s; }
6580         union U4 { U3 s; }
6581         union U5 { U4 s; }
6582         union U6 { U5 s; }
6583         union U7 { U6[0] s; }
6584         union U8 { U7 s; }
6585         union U9 { U8 s; }
6586         union U10 { U9 s; }
6587         mixin testWithQualifiers!(U1, true);
6588         mixin testWithQualifiers!(U2, true);
6589         mixin testWithQualifiers!(U3, true);
6590         mixin testWithQualifiers!(U4, true);
6591         mixin testWithQualifiers!(U5, true);
6592         mixin testWithQualifiers!(U6, true);
6593         mixin testWithQualifiers!(U7, false);
6594         mixin testWithQualifiers!(U8, false);
6595         mixin testWithQualifiers!(U9, false);
6596         mixin testWithQualifiers!(U10, false);
6597     }
6598 }
6599 
6600 // hasIndirections with classes and interfaces
6601 @safe unittest
6602 {
6603     import phobos.sys.meta : AliasSeq;
6604 
6605     alias testWithQualifiers = assertWithQualifiers!hasIndirections;
6606 
6607     {
6608         class C {}
6609         mixin testWithQualifiers!(C, true);
6610     }
6611 
6612     foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
6613                           float, double, real, char, wchar, dchar, int function(string),
6614                           int[int], string delegate(int)))
6615     {
6616         {
6617             class C { T member; }
6618             mixin testWithQualifiers!(C, true);
6619         }
6620         {
6621             class C { const T member; }
6622             mixin testWithQualifiers!(C, true);
6623         }
6624         {
6625             class C { immutable T member; }
6626             mixin testWithQualifiers!(C, true);
6627         }
6628         {
6629             class C { shared T member; }
6630             mixin testWithQualifiers!(C, true);
6631         }
6632     }
6633 
6634     {
6635         interface I {}
6636         mixin testWithQualifiers!(I, true);
6637     }
6638 }
6639 
6640 /++
6641     Takes a type which is an associative array and evaluates to the type of the
6642     keys in that associative array.
6643 
6644     See_Also:
6645         $(LREF ValueType)
6646   +/
6647 alias KeyType(V : V[K], K) = K;
6648 
6649 ///
6650 @safe unittest
6651 {
6652     static assert(is(KeyType!(int[string]) == string));
6653     static assert(is(KeyType!(string[int]) == int));
6654 
6655     static assert(is(KeyType!(string[const int]) == const int));
6656     static assert(is(KeyType!(const int[string]) == string));
6657 
6658     struct S
6659     {
6660         int i;
6661     }
6662 
6663     string[S] aa1;
6664     static assert(is(KeyType!(typeof(aa1)) == S));
6665 
6666     S[string] aa2;
6667     static assert(is(KeyType!(typeof(aa2)) == string));
6668 
6669     KeyType!(typeof(aa1)) key1 = S(42);
6670     KeyType!(typeof(aa2)) key2 = "foo";
6671 
6672     // Key types with indirections have their inner layers treated as const
6673     // by the compiler, because the values of keys can't change, or the hash
6674     // value could change, putting the associative array in an invalid state.
6675     static assert(is(KeyType!(bool[string[]]) == const(string)[]));
6676     static assert(is(KeyType!(bool[int*]) == const(int)*));
6677 
6678     // If the given type is not an AA, then KeyType won't compile.
6679     static assert(!__traits(compiles, KeyType!int));
6680     static assert(!__traits(compiles, KeyType!(int[])));
6681 }
6682 
6683 /++
6684     Takes a type which is an associative array and evaluates to the type of the
6685     values in that associative array.
6686 
6687     See_Also:
6688         $(LREF KeyType)
6689   +/
6690 alias ValueType(V : V[K], K) = V;
6691 
6692 ///
6693 @safe unittest
6694 {
6695     static assert(is(ValueType!(int[string]) == int));
6696     static assert(is(ValueType!(string[int]) == string));
6697 
6698     static assert(is(ValueType!(string[const int]) == string));
6699     static assert(is(ValueType!(const int[string]) == const int));
6700 
6701     struct S
6702     {
6703         int i;
6704     }
6705 
6706     string[S] aa1;
6707     static assert(is(ValueType!(typeof(aa1)) == string));
6708 
6709     S[string] aa2;
6710     static assert(is(ValueType!(typeof(aa2)) == S));
6711 
6712     ValueType!(typeof(aa1)) value1 = "foo";
6713     ValueType!(typeof(aa2)) value2 = S(42);
6714 
6715     // If the given type is not an AA, then ValueType won't compile.
6716     static assert(!__traits(compiles, ValueType!int));
6717     static assert(!__traits(compiles, ValueType!(int[])));
6718 }
6719 
6720 /++
6721     Evaluates to the original / ultimate base type of an enum type - or for
6722     non-enum types, it evaluates to the type that it's given.
6723 
6724     If the base type of the given enum type is not an enum, then the result of
6725     OriginalType is its direct base type. However, if the base type of the
6726     given enum is also an enum, then OriginalType gives the ultimate base type
6727     - that is, it keeps getting the base type for each succesive enum in the
6728     chain until it gets to a base type that isn't an enum, and that's the
6729     result. So, the result will never be an enum type.
6730 
6731     If the given type has any qualifiers, the result will have those same
6732     qualifiers.
6733   +/
6734 version (StdDdoc) template OriginalType(T)
6735 {
6736     import core.internal.traits : CoreOriginalType = OriginalType;
6737     alias OriginalType = CoreOriginalType!T;
6738 }
6739 else
6740 {
6741     import core.internal.traits : CoreOriginalType = OriginalType;
6742     alias OriginalType = CoreOriginalType;
6743 }
6744 
6745 ///
6746 @safe unittest
6747 {
6748     enum E { a, b, c }
6749     static assert(is(OriginalType!E == int));
6750 
6751     enum F : E { x = E.a }
6752     static assert(is(OriginalType!F == int));
6753 
6754     enum G : F { y = F.x }
6755     static assert(is(OriginalType!G == int));
6756     static assert(is(OriginalType!(const G) == const int));
6757     static assert(is(OriginalType!(immutable G) == immutable int));
6758     static assert(is(OriginalType!(shared G) == shared int));
6759 
6760     enum C : char { a = 'a', b = 'b' }
6761     static assert(is(OriginalType!C == char));
6762 
6763     enum D : string { d = "dlang" }
6764     static assert(is(OriginalType!D == string));
6765 
6766     static assert(is(OriginalType!int == int));
6767     static assert(is(OriginalType!(const long) == const long));
6768     static assert(is(OriginalType!string == string));
6769 
6770     // OriginalType gets the base type of enums and for all other types gives
6771     // the same type back. It does nothing special for other types - like
6772     // classes - where one could talk about the type having a base type.
6773     class Base {}
6774     class Derived : Base {}
6775     static assert(is(OriginalType!Base == Base));
6776     static assert(is(OriginalType!Derived == Derived));
6777 }
6778 
6779 /++
6780     PropertyType evaluates to the type of the symbol as an expression (i.e. the
6781     type of the expression when the symbol is used in an expression by itself),
6782     and SymbolType evaluates to the type of the given symbol as a symbol (i.e.
6783     the type of the symbol itself).
6784 
6785     Unlike with $(K_TYPEOF), $(K_PROPERTY) has no effect on the result of
6786     either PropertyType or SymbolType.
6787 
6788     TLDR, PropertyType should be used when code is going to use a symbol as if
6789     it were a getter property (without caring whether the symbol is a variable
6790     or a function), and the code needs to know the type of that property and
6791     $(I not) the type of the symbol itself (since with functions, they're not
6792     the same thing). So, it's treating the symbol as an expression on its own
6793     and giving the type of that expression rather than giving the type of the
6794     symbol itself. And it's named PropertyType rather than something like
6795     $(D ExpressionType), because it's used in situations where the code is
6796     treating the symbol as a getter property, and it does not operate on
6797     expressions in general. SymbolType should then be used in situations where
6798     the code needs to know the type of the symbol itself.
6799 
6800     As for why PropertyType and SymbolType are necessary, and $(K_TYPEOF) is
6801     not sufficient, $(K_TYPEOF) gives both the types of symbols and the types
6802     of expressions. When it's given something that's clearly an expression -
6803     e.g. $(D typeof(foo + bar)) or $(D typeof(foo())), then the result is the
6804     type of that expression. However, when $(K_TYPEOF) is given a symbol, what
6805     $(K_TYPEOF) does depends on the symbol, which can make using it correctly
6806     in generic code difficult.
6807 
6808     For symbols that don't have types, naturally, $(K_TYPEOF) doesn't even
6809     compile (e.g. $(D typeof(int)) won't compile, because in D, types don't
6810     themselves have types), so the question is what happens with $(K_TYPEOF)
6811     and symbols which do have types.
6812 
6813     For symbols which have types and are not functions, what $(K_TYPEOF) does
6814     is straightforward, because there is no difference between the type of the
6815     symbol and the type of the expression - e.g. if $(D foo) is a variable of
6816     type $(K_INT), then $(D typeof(foo)) would be $(K_INT), because the
6817     variable itself is of type $(K_INT), and if the variable is used as an
6818     expression (e.g. when it's returned from a function or passed to a
6819     function), then that expression is also of type $(K_INT).
6820 
6821     However, for functions (particularly functions which don't require
6822     arguments), things aren't as straightforward. Should $(D typeof(foo)) give
6823     the type of the function itself or the type of the expression? If parens
6824     always had to be used when calling a function, then $(D typeof(foo)) would
6825     clearly be the type of the function itself, whereas $(D typeof(foo()))
6826     would be the type of the expression (which would be the return type of the
6827     function so long as $(D foo) could be called with no arguments, and it
6828     wouldn't compile otherwise, because the expression would be invalid).
6829     However, because parens are optional when calling a function that has no
6830     arguments, $(D typeof(foo)) is ambiguous. There's no way to know which the
6831     programmer actually intended, but the compiler has to either make it an
6832     error or choose between giving the type of the symbol or the type of the
6833     expression.
6834 
6835     So, the issue here is functions which can be treated as getter properties,
6836     because they can be called without parens and thus syntactically look
6837     exactly like a variable when they're used. Any function which requires
6838     arguments (including when a function is used as a setter property) does not
6839     have this problem, because it isn't a valid expression when used on its own
6840     (it needs to be assigned to or called with parens in order to be a valid
6841     expression).
6842 
6843     What the compiler currently does when it encounters this ambiguity depends
6844     on the $(K_PROPERTY) attribute. If the function does not have the
6845     $(K_PROPERTY) attribute, then $(D typeof(foo)) will give the type of the
6846     symbol - e.g. $(D int()) if the signature for $(D foo) were $(D int foo()).
6847     However, if the function $(I does) have the $(K_PROPERTY) attribute, then
6848     $(D typeof(foo)) will give the type of the expression. So, if $(D foo) were
6849     $(D @property int foo()), then $(D typeof(foo)) would give $(K_INT) rather
6850     than $(D int()). The idea behind this is that $(K_PROPERTY) functions are
6851     supposed to act like variables, and using $(K_TYPEOF) on a variable of type
6852     $(K_INT) would give $(K_INT), not $(D int()). So, with this behavior of
6853     $(K_TYPEOF), a $(K_PROPERTY) function is closer to being a drop-in
6854     replacement for a variable.
6855 
6856     The problem with this though is two-fold. One, it means that $(K_TYPEOF)
6857     cannot be relied on to give the type of the symbol when given a symbol on
6858     its own, forcing code that needs the actual type of the symbol to work
6859     around $(K_PROPERTY). And two, because parens are optional on functions
6860     which can be called without arguments, whether the function is marked with
6861     $(K_PROPERTY) or not is irrevelant to whether the symbol is going to be
6862     used as if it were a variable, and so it's irrelevant to code that's trying
6863     to get the type of the expression when the symbol is used like a getter
6864     property. If optional parens were removed from the language (as was
6865     originally the intent when $(K_PROPERTY) was introduced), then that would
6866     fix the second problem, but it would still leave the first problem.
6867 
6868     So, $(K_PROPERTY) is solving the problem in the wrong place. It's the code
6869     doing the type introspection which needs to decide whether to get the type
6870     of a symbol as if it were a getter property or whether to get the type of
6871     the symbol itself. It's the type introspection code which knows which is
6872     relevant for what it's doing, and a function could be used both in code
6873     which needs to treat it as a getter property and in code which needs to get
6874     the type of the symbol itself (e.g. because it needs to get the attributes
6875     on the function).
6876 
6877     All of this means that $(K_TYPEOF) by itself is unreliable when used on a
6878     symbol. In practice, the programmer needs to indicate whether they want the
6879     type of the symbol itself or the type of the symbol as a getter property in
6880     an expression, and leaving it up to $(K_TYPEOF) is simply too error-prone.
6881     So, ideally, $(K_TYPEOF) would be split up into two separate constructs,
6882     but that would involve adding more keywords (and break a lot of existing
6883     code if $(K_TYPEOF) were actually removed).
6884 
6885     So, phobos.sys.traits provides SymbolType and PropertyType. They're both
6886     traits that take a symbol and give the type for that symbol. However,
6887     SymbolType gives the type of the symbol itself, whereas PropertyType gives
6888     the type of the symbol as if it were used as a getter property in an
6889     expression. Neither is affected by whether the symbol is marked with
6890     $(K_PROPERTY). So, code that needs to get information about the symbol
6891     itself should use SymbolType rather than $(K_TYPEOF) or PropertyType,
6892     whereas code that needs to get the type of the symbol as a getter property
6893     within an expression should use PropertyType.
6894 
6895     The use of $(K_TYPEOF) should then be restricted to situations where code
6896     is getting the type of an expression which isn't a symbol (or code where
6897     it's already known that the symbol isn't a function). Also, since
6898     template alias parameters only accept symbols, any expressions which aren't
6899     symbols won't compile with SymbolType or PropertyType anyway.
6900 
6901     SymbolType and PropertyType must be given a symbol which has a type (so,
6902     not something like a type or an uninstantiated template). Symbols
6903     which don't have types will fail the template constraint.
6904 
6905     For both SymbolType and PropertyType, if they are given a symbol which has
6906     a type, and that symbol is not a function, the result will be the same as
6907     $(K_TYPEOF) (since in such cases, the type of the symbol and the type of
6908     the expression are the same). The difference comes in with functions.
6909 
6910     When SymbolType is given any symbol which is a function, the result will be
6911     the type of the function itself regardless of whether the function is
6912     marked with $(K_PROPERTY). This makes it so that in all situations where
6913     the type of the symbol is needed, SymbolType can be used to get the type of
6914     the symbol without having to worry about whether it's a function marked
6915     with $(K_PROPERTY).
6916 
6917     When PropertyType is given any function which can be used as a getter
6918     property, the result will be the type of the symbol as an expression - i.e.
6919     the return type of the function (in effect, this means that it treats all
6920     functions as if they were marked with $(K_PROPERTY)). Whether the function
6921     is actually marked with $(K_PROPERTY) or not is irrelevant.
6922 
6923     If PropertyType is given any function which which cannot be used as a
6924     getter property (i.e. it requires arguments or returns $(K_VOID)), the
6925     template constraint will reject it, and PropertyType will fail to compile.
6926     This is equivalent to what $(K_TYPEOF) does when it's given a $(K_PROPERTY)
6927     function which is a setter, since it's not a valid expression on its own.
6928 
6929     So, for $(D PropertyType!foo), if $(D foo) is a function, the result is
6930     equivalent to $(D typeof(foo())) (and for non-functions, it's equivalent to
6931     $(D typeof(foo))).
6932 
6933     To summarize, SymbolType should be used when code needs to get the type of
6934     the symbol itself; PropertyType should be used when code needs to get the
6935     type of the symbol when it's used in an expression as a getter property
6936     (generally because the code doesn't care whether the symbol is a variable
6937     or a function); and $(K_TYPEOF) should be used when getting the type of an
6938     expression which is not a symbol.
6939 
6940     See_Also:
6941         $(DDSUBLINK spec/type, typeof, The language spec for typeof)
6942   +/
6943 template PropertyType(alias sym)
6944 if (is(typeof(sym)) && (!is(typeof(sym) == return) ||
6945                         (is(typeof(sym())) && !is(typeof(sym()) == void))))
6946 {
6947     // This handles functions which don't have a context pointer.
6948     static if (is(typeof(&sym) == T*, T) && is(T == function))
6949     {
6950         // Note that we can't use is(T R == return) to get the return type,
6951         // because the first overload isn't necessarily the getter function,
6952         // and is(T R == return) will give us the first overload if the function
6953         // doesn't have @property on it (whereas if it does have @property, it
6954         // will give use the getter if there is one). However, we at least know
6955         // that there's a getter function, because the template constraint
6956         // validates that sym() compiles (and returns something) if it's a
6957         // function, function pointer, or delegate.
6958         alias PropertyType = typeof(sym());
6959     }
6960     // This handles functions which do have a context pointer.
6961     else static if (is(typeof(&sym) T == delegate) && is(T R == return))
6962     {
6963         // See the comment above for why we can't get the return type the
6964         // normal way.
6965         alias PropertyType = typeof(sym());
6966     }
6967     // This handles everything which isn't a function.
6968     else
6969         alias PropertyType = typeof(sym);
6970 }
6971 
6972 /++ Ditto +/
6973 template SymbolType(alias sym)
6974 if (!is(sym))
6975 {
6976     // This handles functions which don't have a context pointer.
6977     static if (is(typeof(&sym) == T*, T) && is(T == function))
6978         alias SymbolType = T;
6979     // This handles functions which do have a context pointer.
6980     else static if (is(typeof(&sym) T == delegate))
6981         alias SymbolType = T;
6982     // This handles everything which isn't a function.
6983     else
6984         alias SymbolType = typeof(sym);
6985 }
6986 
6987 ///
6988 @safe unittest
6989 {
6990     int i;
6991     static assert( is(SymbolType!i == int));
6992     static assert( is(PropertyType!i == int));
6993     static assert( is(typeof(i) == int));
6994 
6995     string str;
6996     static assert( is(SymbolType!str == string));
6997     static assert( is(PropertyType!str == string));
6998     static assert( is(typeof(str) == string));
6999 
7000     // ToFunctionType is used here to get around the fact that we don't have a
7001     // way to write out function types in is expressions (whereas we can write
7002     // out the type of a function pointer), which is a consequence of not being
7003     // able to declare variables with a function type (as opposed to a function
7004     // pointer type). That being said, is expressions are pretty much the only
7005     // place where writing out a function type would make sense.
7006 
7007     // The function type has more attributes than the function declaration,
7008     // because the attributes are inferred for nested functions.
7009 
7010     static string func() { return ""; }
7011     static assert( is(SymbolType!func ==
7012                       ToFunctionType!(string function()
7013                                       @safe pure nothrow @nogc)));
7014     static assert( is(PropertyType!func == string));
7015     static assert( is(typeof(func) == SymbolType!func));
7016 
7017     int function() funcPtr;
7018     static assert( is(SymbolType!funcPtr == int function()));
7019     static assert( is(PropertyType!funcPtr == int function()));
7020     static assert( is(typeof(funcPtr) == int function()));
7021 
7022     int delegate() del;
7023     static assert( is(SymbolType!del == int delegate()));
7024     static assert( is(PropertyType!del == int delegate()));
7025     static assert( is(typeof(del) == int delegate()));
7026 
7027     @property static int prop() { return 0; }
7028     static assert( is(SymbolType!prop ==
7029                       ToFunctionType!(int function()
7030                                       @property @safe pure nothrow @nogc)));
7031     static assert( is(PropertyType!prop == int));
7032     static assert( is(typeof(prop) == PropertyType!prop));
7033 
7034     // Functions which cannot be used as getter properties (i.e. they require
7035     // arguments and/or return void) do not compile with PropertyType.
7036     static int funcWithArg(int i) { return i; }
7037     static assert( is(SymbolType!funcWithArg ==
7038                       ToFunctionType!(int function(int)
7039                                       @safe pure nothrow @nogc)));
7040     static assert(!__traits(compiles, PropertyType!funcWithArg));
7041     static assert( is(typeof(funcWithArg) == SymbolType!funcWithArg));
7042 
7043     // Setter @property functions also don't work with typeof, because typeof
7044     // gets the type of the expression rather than the type of the symbol when
7045     // the symbol is a function with @property, and a setter property is not a
7046     // valid expression on its own.
7047     @property static void prop2(int) {}
7048     static assert( is(SymbolType!prop2 ==
7049                       ToFunctionType!(void function(int)
7050                                       @property @safe pure nothrow @nogc)));
7051     static assert(!__traits(compiles, PropertyType!prop2));
7052     static assert(!__traits(compiles, typeof(prop2)));
7053 
7054     // Expressions which aren't symbols don't work with alias parameters and
7055     // thus don't work with SymbolType or PropertyType.
7056     static assert(!__traits(compiles, PropertyType!(i + 42)));
7057     static assert(!__traits(compiles, SymbolType!(i + 42)));
7058     static assert( is(typeof(i + 42) == int));
7059 
7060     // typeof will work with a function that takes arguments so long as it's
7061     // used in a proper expression.
7062     static assert( is(typeof(funcWithArg(42)) == int));
7063     static assert( is(typeof(prop2 = 42) == void));
7064     static assert( is(typeof(prop2(42)) == void));
7065 }
7066 
7067 /++
7068     With templated types or functions, a specific instantiation should be
7069     passed to SymbolType or PropertyType, not the symbol for the template
7070     itself. If $(K_TYPEOF), SymbolType, or PropertyType is used on a template
7071     (rather than an instantiation of the template), the result will be
7072     $(K_VOID), because the template itself does not have a type.
7073   +/
7074 @safe unittest
7075 {
7076     static T func(T)() { return T.init; }
7077 
7078     static assert(is(SymbolType!func == void));
7079     static assert(is(PropertyType!func == void));
7080     static assert(is(typeof(func) == void));
7081 
7082     static assert(is(SymbolType!(func!int) ==
7083                      ToFunctionType!(int function()
7084                                      @safe pure nothrow @nogc)));
7085     static assert(is(PropertyType!(func!int) == int));
7086     static assert(is(typeof(func!int) == SymbolType!(func!int)));
7087 
7088     static assert(is(SymbolType!(func!string) ==
7089                      ToFunctionType!(string function()
7090                                      @safe pure nothrow @nogc)));
7091     static assert(is(PropertyType!(func!string) == string));
7092     static assert(is(typeof(func!string) == SymbolType!(func!string)));
7093 }
7094 
7095 /++
7096     If a function is overloaded, then when using it as a symbol to pass to
7097     $(K_TYPEOF), the compiler typically selects the first overload. However, if
7098     the functions are marked with $(K_PROPERTY), and one of the overloads is a
7099     getter property, then $(K_TYPEOF) will select the getter property (or fail
7100     to compile if they're all setter properties). This is because it's getting
7101     the type of the function as an expression rather than doing introspection
7102     on the function itself.
7103 
7104     SymbolType always gives the type of the first overload (effectively ignoring
7105     $(K_PROPERTY)), and PropertyType always gives the getter ovrerload
7106     (effectively treating all functions as if they had $(K_PROPERTY)).
7107 
7108     If code needs to get the symbol for a specific overload, then
7109     $(DDSUBLINK spec/traits, getOverloads, $(D __traits(getOverloads, ...))
7110     must be used.
7111 
7112     In general, $(D getOverloads) should be used when using SymbolType, since
7113     there's no guarantee that the first one is the correct one (and often, code
7114     will need to check all of the overloads), whereas with PropertyType, it
7115     doesn't usually make sense to get specific overloads, because there can
7116     only ever be one overload which works as a getter property, and using
7117     PropertyType on the symbol for the function will give that overload if it's
7118     present, regardless of which overload is first (and it will fail to compile
7119     if there is no overload which can be called as a getter).
7120   +/
7121 @safe unittest
7122 {
7123     static struct S
7124     {
7125         string foo();
7126         void foo(string);
7127         bool foo(string, int);
7128 
7129         @property void bar(int);
7130         @property int bar();
7131     }
7132 
7133     {
7134         static assert( is(SymbolType!(S.foo) ==
7135                           ToFunctionType!(string function())));
7136         static assert( is(PropertyType!(S.foo) == string));
7137         static assert( is(typeof(S.foo) == SymbolType!(S.foo)));
7138 
7139         alias overloads = __traits(getOverloads, S, "foo");
7140 
7141         // string foo();
7142         static assert( is(SymbolType!(overloads[0]) == function));
7143         static assert( is(PropertyType!(overloads[0]) == string));
7144         static assert( is(typeof(overloads[0]) == function));
7145 
7146         static assert( is(SymbolType!(overloads[0]) ==
7147                           ToFunctionType!(string function())));
7148         static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7149 
7150         // void foo(string);
7151         static assert( is(SymbolType!(overloads[1]) == function));
7152         static assert(!__traits(compiles, PropertyType!(overloads[1])));
7153         static assert( is(typeof(overloads[1]) == function));
7154 
7155         static assert( is(SymbolType!(overloads[1]) ==
7156                           ToFunctionType!(void function(string))));
7157         static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7158 
7159         // void foo(string, int);
7160         static assert( is(SymbolType!(overloads[2]) == function));
7161         static assert(!__traits(compiles, PropertyType!(overloads[2])));
7162         static assert( is(typeof(overloads[2]) == function));
7163 
7164         static assert( is(SymbolType!(overloads[2]) ==
7165                           ToFunctionType!(bool function(string, int))));
7166         static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2])));
7167     }
7168     {
7169         static assert( is(SymbolType!(S.bar) ==
7170                           ToFunctionType!(void function(int) @property)));
7171         static assert( is(PropertyType!(S.bar) == int));
7172         static assert( is(typeof(S.bar) == PropertyType!(S.bar)));
7173 
7174         alias overloads = __traits(getOverloads, S, "bar");
7175 
7176         // @property void bar(int);
7177         static assert( is(SymbolType!(overloads[0]) == function));
7178         static assert(!__traits(compiles, PropertyType!(overloads[0])));
7179         static assert(!__traits(compiles, typeof(overloads[0])));
7180 
7181         static assert( is(SymbolType!(overloads[0]) ==
7182                           ToFunctionType!(void function(int) @property)));
7183 
7184         // @property int bar();
7185         static assert( is(SymbolType!(overloads[1]) == function));
7186         static assert( is(PropertyType!(overloads[1]) == int));
7187         static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
7188 
7189         static assert( is(SymbolType!(overloads[1]) ==
7190                           ToFunctionType!(int function() @property)));
7191     }
7192 }
7193 
7194 @safe unittest
7195 {
7196     {
7197         string str;
7198         int i;
7199 
7200         static assert(!__traits(compiles, SymbolType!int));
7201         static assert(!__traits(compiles, SymbolType!(str ~ "more str")));
7202         static assert(!__traits(compiles, SymbolType!(i + 42)));
7203         static assert(!__traits(compiles, SymbolType!(&i)));
7204 
7205         static assert(!__traits(compiles, PropertyType!int));
7206         static assert(!__traits(compiles, PropertyType!(str ~ "more str")));
7207         static assert(!__traits(compiles, PropertyType!(i + 42)));
7208         static assert(!__traits(compiles, PropertyType!(&i)));
7209     }
7210 
7211     static assert( is(SymbolType!42 == int));
7212     static assert( is(SymbolType!"dlang" == string));
7213 
7214     int var;
7215 
7216     int funcWithContext() { return var; }
7217     static assert( is(SymbolType!funcWithContext ==
7218                       ToFunctionType!(int function()
7219                                       @safe pure nothrow @nogc)));
7220     static assert( is(PropertyType!funcWithContext == int));
7221     static assert( is(typeof(funcWithContext) == SymbolType!funcWithContext));
7222 
7223     @property int propWithContext() { return var; }
7224     static assert( is(SymbolType!propWithContext == function));
7225     static assert( is(SymbolType!propWithContext ==
7226                       ToFunctionType!(int function() @property @safe pure nothrow @nogc)));
7227     static assert( is(PropertyType!propWithContext == int));
7228     static assert( is(typeof(propWithContext) == PropertyType!propWithContext));
7229 
7230     // For those who might be confused by this sort of declaration, this is a
7231     // property function which returns a function pointer that takes no
7232     // arguments and returns int, which gets an even uglier signature when
7233     // writing out the type for a pointer to such a property function.
7234     static int function() propFuncPtr() @property { return null; }
7235     static assert( is(SymbolType!propFuncPtr == function));
7236     static assert( is(SymbolType!propFuncPtr ==
7237                       ToFunctionType!(int function() function() @property @safe pure nothrow @nogc)));
7238     static assert( is(PropertyType!propFuncPtr == int function()));
7239     static assert( is(typeof(propFuncPtr) == PropertyType!propFuncPtr));
7240 
7241     static int delegate() propDel() @property { return null; }
7242     static assert( is(SymbolType!propDel == function));
7243     static assert( is(SymbolType!propDel ==
7244                       ToFunctionType!(int delegate() function() @property @safe pure nothrow @nogc)));
7245     static assert( is(PropertyType!propDel == int delegate()));
7246     static assert( is(typeof(propDel) == PropertyType!propDel));
7247 
7248     int function() propFuncPtrWithContext() @property { ++var; return null; }
7249     static assert( is(SymbolType!propFuncPtrWithContext == function));
7250     static assert( is(SymbolType!propFuncPtrWithContext ==
7251                       ToFunctionType!(int function() function() @property @safe pure nothrow @nogc)));
7252     static assert( is(PropertyType!propFuncPtrWithContext == int function()));
7253     static assert( is(typeof(propFuncPtrWithContext) == PropertyType!propFuncPtrWithContext));
7254 
7255     int delegate() propDelWithContext() @property { ++var; return null; }
7256     static assert( is(SymbolType!propDelWithContext == function));
7257     static assert( is(SymbolType!propDelWithContext ==
7258                       ToFunctionType!(int delegate() function() @property @safe pure nothrow @nogc)));
7259     static assert( is(PropertyType!propDelWithContext == int delegate()));
7260     static assert( is(typeof(propDelWithContext) == PropertyType!propDelWithContext));
7261 
7262     const int ci;
7263     static assert( is(SymbolType!ci == const int));
7264     static assert( is(PropertyType!ci == const int));
7265     static assert( is(typeof(ci) == PropertyType!ci));
7266 
7267     shared int si;
7268     static assert( is(SymbolType!si == shared int));
7269     static assert( is(PropertyType!si == shared int));
7270     static assert( is(typeof(si) == PropertyType!si));
7271 
7272     static struct S
7273     {
7274         int i;
7275         @disable this(this);
7276     }
7277     static assert(!__traits(isCopyable, S));
7278 
7279     S s;
7280     static assert( is(SymbolType!s == S));
7281     static assert( is(PropertyType!s == S));
7282     static assert( is(typeof(s) == SymbolType!s));
7283 
7284     static ref S foo();
7285     static void bar(ref S);
7286 
7287     static @property ref S bob();
7288     static @property void sally(ref S);
7289 
7290     // The aliases are due to https://github.com/dlang/dmd/issues/17505
7291     // Apparently, aliases are special-cased to work with function pointer
7292     // signatures which return by ref, and we can't do it elsewhere.
7293     alias FooPtr = ref S function();
7294     static assert( is(SymbolType!foo == ToFunctionType!FooPtr));
7295     static assert( is(PropertyType!foo == S));
7296     static assert( is(typeof(foo) == SymbolType!foo));
7297 
7298     static assert( is(SymbolType!bar == ToFunctionType!(void function(ref S))));
7299     static assert(!__traits(compiles, PropertyType!bar));
7300     static assert( is(typeof(bar) == SymbolType!bar));
7301 
7302     alias BobPtr = ref S function() @property;
7303     static assert( is(SymbolType!bob == ToFunctionType!BobPtr));
7304     static assert( is(PropertyType!bob == S));
7305     static assert( is(typeof(bob) == S));
7306     static assert( is(typeof(bob) == PropertyType!bob));
7307 
7308     static assert( is(SymbolType!sally == ToFunctionType!(void function(ref S) @property)));
7309     static assert(!__traits(compiles, PropertyType!sally));
7310     static assert(!__traits(compiles, typeof(sally)));
7311 
7312     string defaultArgs1(int i = 0);
7313     void defaultArgs2(string, int i = 0);
7314 
7315     static assert( is(SymbolType!defaultArgs1 == ToFunctionType!(string function(int))));
7316     static assert( is(PropertyType!defaultArgs1 == string));
7317     static assert( is(typeof(defaultArgs1) == SymbolType!defaultArgs1));
7318 
7319     static assert( is(SymbolType!defaultArgs2 == ToFunctionType!(void function(string, int))));
7320     static assert(!__traits(compiles, PropertyType!defaultArgs2));
7321     static assert( is(typeof(defaultArgs2) == SymbolType!defaultArgs2));
7322 
7323     @property string defaultArgsProp1(int i = 0);
7324     @property void defaultArgsProp2(string, int i = 0);
7325 
7326     static assert( is(SymbolType!defaultArgsProp1 == ToFunctionType!(string function(int) @property)));
7327     static assert( is(PropertyType!defaultArgsProp1 == string));
7328     static assert( is(typeof(defaultArgsProp1) == PropertyType!defaultArgsProp1));
7329 
7330     static assert( is(SymbolType!defaultArgsProp2 == ToFunctionType!(void function(string, int) @property)));
7331     static assert(!__traits(compiles, PropertyType!defaultArgsProp2));
7332     static assert(!__traits(compiles, typeof(defaultArgsProp2)));
7333 
7334     int returningSetter(string);
7335     @property int returningSetterProp(string);
7336 
7337     static assert( is(SymbolType!returningSetter == ToFunctionType!(int function(string))));
7338     static assert(!__traits(compiles, PropertyType!returningSetter));
7339     static assert( is(typeof(returningSetter) == SymbolType!returningSetter));
7340 
7341     static assert( is(SymbolType!returningSetterProp == ToFunctionType!(int function(string) @property)));
7342     static assert(!__traits(compiles, PropertyType!returningSetterProp));
7343     static assert(!__traits(compiles, typeof(returningSetterProp)));
7344 }
7345 
7346 // These are for the next unittest block to test overloaded free functions (in
7347 // addition to the overloaded member functions and static functions that it
7348 // tests). That way, if there are any differences in how free functions and
7349 // member functions are handled, we'll catch those bugs (be they compiler bugs
7350 // or bugs in phobos.sys.traits).
7351 version (PhobosUnittest)
7352 {
7353     private void modFunc1();
7354     private void modFunc1(string);
7355     private int modFunc1(string, int);
7356 
7357     private int modFunc2();
7358     private int modFunc2(string);
7359     private string modFunc2(string, int);
7360 
7361     private void modFunc3(int*);
7362     private void modFunc3(float);
7363     private string modFunc3(int a = 0);
7364 
7365     private int modGetterFirst();
7366     private void modGetterFirst(int);
7367 
7368     private void modSetterFirst(int);
7369     private int modSetterFirst();
7370 
7371     private void modSetterOnly(string);
7372     private void modSetterOnly(int);
7373 
7374     private @property int modPropGetterFirst();
7375     private @property void modPropGetterFirst(int);
7376 
7377     private @property void modPropSetterFirst(int);
7378     private @property int modPropSetterFirst();
7379 
7380     private @property void modPropSetterOnly(string);
7381     private @property void modPropSetterOnly(int);
7382 
7383     private int function() @property modGetterFirstFuncPtr();
7384     private void modGetterFirstFuncPtr(int function() @property);
7385 
7386     private void modSetterFirstFuncPtr(int function() @property);
7387     private int function() @property modSetterFirstFuncPtr();
7388 
7389     private int function() @property modPropGetterFirstFuncPtr() @property;
7390     private void modPropGetterFirstFuncPtr(int function() @property) @property;
7391 
7392     private void modPropSetterFirstFuncPtr(int function() @property) @property;
7393     private int function() @property modPropSetterFirstFuncPtr() @property;
7394 }
7395 
7396 @safe unittest
7397 {
7398     // Note that with overloads without @property, typeof gives the first
7399     // overload, whereas with overloads with @property, typeof gives the return
7400     // type of the getter overload no matter where it is in the order.
7401     // PropertyType needs to always give the getter overload whether @property
7402     // is used or not, since that's the type of the symbol when used as a
7403     // getter property in an expression.
7404     {
7405         alias module_ = __traits(parent, __traits(parent, {}));
7406 
7407         // void modFunc1();
7408         // void modFunc1(string);
7409         // int modFunc1(string, int);
7410         {
7411             static assert( is(SymbolType!modFunc1 == ToFunctionType!(void function())));
7412             static assert(!__traits(compiles, PropertyType!modFunc1));
7413             static assert( is(typeof(modFunc1) == SymbolType!modFunc1));
7414 
7415             alias overloads = __traits(getOverloads, module_, "modFunc1");
7416             static assert(overloads.length == 3);
7417 
7418             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function())));
7419             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7420             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7421 
7422             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string))));
7423             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7424             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7425 
7426             static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(int function(string, int))));
7427             static assert(!__traits(compiles, PropertyType!(overloads[2])));
7428             static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2])));
7429         }
7430 
7431         // int modFunc2();
7432         // int modFunc2(string);
7433         // string modFunc2(string, int);
7434         {
7435             static assert( is(SymbolType!modFunc2 == ToFunctionType!(int function())));
7436             static assert( is(PropertyType!modFunc2 == int));
7437             static assert( is(typeof(modFunc2) == SymbolType!modFunc2));
7438 
7439             alias overloads = __traits(getOverloads, module_, "modFunc2");
7440             static assert(overloads.length == 3);
7441 
7442             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function())));
7443             static assert( is(PropertyType!(overloads[0]) == int));
7444             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7445 
7446             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string))));
7447             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7448             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7449 
7450             static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(string function(string, int))));
7451             static assert(!__traits(compiles, PropertyType!(overloads[2])));
7452             static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2])));
7453         }
7454 
7455         // void modFunc3(int*);
7456         // void modFunc3(float);
7457         // string modFunc3(int a = 0);
7458         {
7459             static assert( is(SymbolType!modFunc3 == ToFunctionType!(void function(int*))));
7460             static assert( is(PropertyType!modFunc3 == string));
7461             static assert( is(typeof(modFunc3) == SymbolType!modFunc3));
7462 
7463             alias overloads = __traits(getOverloads, module_, "modFunc3");
7464             static assert(overloads.length == 3);
7465 
7466             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int*))));
7467             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7468             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7469 
7470             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(float))));
7471             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7472             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7473 
7474             static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(string function(int))));
7475             static assert( is(PropertyType!(overloads[2]) == string));
7476             static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2])));
7477         }
7478 
7479         // int modGetterFirst();
7480         // void modGetterFirst(int);
7481         {
7482             static assert( is(SymbolType!modGetterFirst == ToFunctionType!(int function())));
7483             static assert( is(PropertyType!modGetterFirst == int));
7484             static assert( is(typeof(modGetterFirst) == SymbolType!modGetterFirst));
7485 
7486             alias overloads = __traits(getOverloads, module_, "modGetterFirst");
7487             static assert(overloads.length == 2);
7488 
7489             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function())));
7490             static assert( is(PropertyType!(overloads[0]) == int));
7491             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7492 
7493             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int))));
7494             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7495             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7496         }
7497 
7498         // void modSetterFirst(int);
7499         // int modSetterFirst();
7500         {
7501             static assert( is(SymbolType!modSetterFirst == ToFunctionType!(void function(int))));
7502             static assert( is(PropertyType!modSetterFirst == int));
7503             static assert( is(typeof(modSetterFirst) == SymbolType!modSetterFirst));
7504 
7505             alias overloads = __traits(getOverloads, module_, "modSetterFirst");
7506             static assert(overloads.length == 2);
7507 
7508             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int))));
7509             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7510             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7511 
7512             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function())));
7513             static assert( is(PropertyType!(overloads[1]) == int));
7514             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7515         }
7516 
7517         // void modSetterOnly(string);
7518         // void modSetterOnly(int);
7519         {
7520             static assert( is(SymbolType!modSetterOnly == ToFunctionType!(void function(string))));
7521             static assert(!__traits(compiles, PropertyType!modSetterOnly));
7522             static assert( is(typeof(modSetterOnly) == SymbolType!modSetterOnly));
7523 
7524             alias overloads = __traits(getOverloads, module_, "modSetterOnly");
7525             static assert(overloads.length == 2);
7526 
7527             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string))));
7528             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7529             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7530 
7531             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int))));
7532             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7533             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7534         }
7535 
7536         // @property int modPropGetterFirst();
7537         // @property void modPropGetterFirst(int);
7538         {
7539             static assert( is(SymbolType!modPropGetterFirst == ToFunctionType!(int function() @property)));
7540             static assert( is(PropertyType!modPropGetterFirst == int));
7541             static assert( is(typeof(modPropGetterFirst) == PropertyType!modPropGetterFirst));
7542 
7543             alias overloads = __traits(getOverloads, module_, "modPropGetterFirst");
7544             static assert(overloads.length == 2);
7545 
7546             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function() @property)));
7547             static assert( is(PropertyType!(overloads[0]) == int));
7548             static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
7549 
7550             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int) @property)));
7551             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7552             static assert(!__traits(compiles, typeof((overloads[1]))));
7553         }
7554 
7555         // @property void modPropSetterFirst(int);
7556         // @property int modPropSetterFirst();
7557         {
7558             static assert( is(SymbolType!modPropSetterFirst == ToFunctionType!(void function(int) @property)));
7559             static assert( is(PropertyType!modPropSetterFirst == int));
7560             static assert( is(typeof(modPropSetterFirst) == PropertyType!modPropSetterFirst));
7561 
7562             alias overloads = __traits(getOverloads, module_, "modPropSetterFirst");
7563             static assert(overloads.length == 2);
7564 
7565             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property)));
7566             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7567             static assert(!__traits(compiles, typeof(overloads[0])));
7568 
7569             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property)));
7570             static assert( is(PropertyType!(overloads[1]) == int));
7571             static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
7572         }
7573 
7574         // @property void modPropSetterOnly(string);
7575         // @property void modPropSetterOnly(int);
7576         {
7577             static assert( is(SymbolType!modPropSetterOnly == ToFunctionType!(void function(string) @property)));
7578             static assert(!__traits(compiles, PropertyType!modPropSetterOnly));
7579             static assert(!__traits(compiles, typeof(modPropSetterOnly)));
7580 
7581             alias overloads = __traits(getOverloads, module_, "modPropSetterOnly");
7582             static assert(overloads.length == 2);
7583 
7584             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string) @property)));
7585             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7586             static assert(!__traits(compiles, typeof(overloads[0])));
7587 
7588             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int) @property)));
7589             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7590             static assert(!__traits(compiles, typeof(overloads[1])));
7591         }
7592 
7593         // int function() @property modGetterFirstFuncPtr();
7594         // void modGetterFirstFuncPtr(int function() @property);
7595         {
7596             static assert( is(SymbolType!modGetterFirstFuncPtr ==
7597                               ToFunctionType!(int function() @property function())));
7598             static assert( is(PropertyType!modGetterFirstFuncPtr == int function() @property));
7599             static assert( is(typeof(modGetterFirstFuncPtr) == SymbolType!modGetterFirstFuncPtr));
7600 
7601             alias overloads = __traits(getOverloads, module_, "modGetterFirstFuncPtr");
7602             static assert(overloads.length == 2);
7603 
7604             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function() @property function())));
7605             static assert( is(PropertyType!(overloads[0]) == int function() @property));
7606             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7607 
7608             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int function() @property))));
7609             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7610             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7611         }
7612 
7613         // void modSetterFirstFuncPtr(int function() @property);
7614         // int function() @property modSetterFirstFuncPtr();
7615         {
7616             static assert( is(SymbolType!modSetterFirstFuncPtr ==
7617                               ToFunctionType!(void function(int function() @property))));
7618             static assert( is(PropertyType!modSetterFirstFuncPtr == int function() @property));
7619             static assert( is(typeof(modSetterFirstFuncPtr) == SymbolType!modSetterFirstFuncPtr));
7620 
7621             alias overloads = __traits(getOverloads, module_, "modSetterFirstFuncPtr");
7622             static assert(overloads.length == 2);
7623 
7624             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int function() @property))));
7625             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7626             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7627 
7628             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property function())));
7629             static assert( is(PropertyType!(overloads[1]) == int function() @property));
7630             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7631         }
7632 
7633         // int function() @property modPropGetterFirstFuncPtr() @property;
7634         // void modPropGetterFirstFuncPtr(int function() @property) @property;
7635         {
7636             static assert( is(SymbolType!modPropGetterFirstFuncPtr ==
7637                               ToFunctionType!(int function() @property function() @property)));
7638             static assert( is(PropertyType!modPropGetterFirstFuncPtr == int function() @property));
7639             static assert( is(typeof(modPropGetterFirstFuncPtr) == PropertyType!modPropGetterFirstFuncPtr));
7640 
7641             alias overloads = __traits(getOverloads, module_, "modPropGetterFirstFuncPtr");
7642             static assert(overloads.length == 2);
7643 
7644             static assert( is(SymbolType!(overloads[0]) ==
7645                               ToFunctionType!(int function() @property function() @property)));
7646             static assert( is(PropertyType!(overloads[0]) == int function() @property));
7647             static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
7648 
7649             static assert( is(SymbolType!(overloads[1]) ==
7650                               ToFunctionType!(void function(int function() @property) @property)));
7651             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7652             static assert(!__traits(compiles, typeof((overloads[1]))));
7653         }
7654 
7655         // void modPropSetterFirstFuncPtr(int function() @property) @property;
7656         // int function() @property modPropSetterFirstFuncPtr() @property;
7657         {
7658             static assert( is(SymbolType!modPropSetterFirstFuncPtr ==
7659                               ToFunctionType!(void function(int function() @property) @property)));
7660             static assert( is(PropertyType!modPropSetterFirstFuncPtr == int function() @property));
7661             static assert( is(typeof(modPropSetterFirstFuncPtr) == PropertyType!modPropSetterFirstFuncPtr));
7662 
7663             alias overloads = __traits(getOverloads, module_, "modPropSetterFirstFuncPtr");
7664             static assert(overloads.length == 2);
7665 
7666             static assert( is(SymbolType!(overloads[0]) ==
7667                               ToFunctionType!(void function(int function() @property) @property)));
7668             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7669             static assert(!__traits(compiles, typeof(overloads[0])));
7670 
7671             static assert( is(SymbolType!(overloads[1]) ==
7672                               ToFunctionType!(int function() @property function() @property)));
7673             static assert( is(PropertyType!(overloads[1]) == int function() @property));
7674             static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
7675         }
7676     }
7677 
7678     {
7679         static struct S
7680         {
7681             int[] arr1;
7682             immutable bool[] arr2;
7683 
7684             void foo();
7685             static void bar();
7686 
7687             long bob();
7688             void sally(long);
7689 
7690             @property long propGetter();
7691             @property void propSetter(int[]);
7692 
7693             static @property long staticPropGetter();
7694             static @property void staticPropSetter(int[]);
7695 
7696             void func1();
7697             void func1(int[]);
7698             long func1(int[], long);
7699 
7700             long func2();
7701             long func2(int[]);
7702             int[] func2(int[], long);
7703 
7704             void func3(long*);
7705             void func3(real);
7706             int[] func3(long a = 0);
7707 
7708             long getterFirst();
7709             void getterFirst(long);
7710 
7711             void setterFirst(long);
7712             long setterFirst();
7713 
7714             void setterOnly(int[]);
7715             void setterOnly(long);
7716 
7717             static long staticGetterFirst();
7718             static void staticGetterFirst(long);
7719 
7720             static void staticSetterFirst(long);
7721             static long staticSetterFirst();
7722 
7723             static void staticSetterOnly(int[]);
7724             static void staticSetterOnly(long);
7725 
7726             @property long propGetterFirst();
7727             @property void propGetterFirst(long);
7728 
7729             @property void propSetterFirst(long);
7730             @property long propSetterFirst();
7731 
7732             @property void propSetterOnly(int[]);
7733             @property void propSetterOnly(long);
7734 
7735             static @property long staticPropGetterFirst();
7736             static @property void staticPropGetterFirst(long);
7737 
7738             static @property void staticPropSetterFirst(long);
7739             static @property long staticPropSetterFirst();
7740 
7741             static @property void staticPropSetterOnly(int[]);
7742             static @property void staticPropSetterOnly(long);
7743 
7744             long function() @property getterFirstFuncPtr();
7745             void getterFirstFuncPtr(long function() @property);
7746 
7747             void setterFirstFuncPtr(long function() @property);
7748             long function() @property setterFirstFuncPtr();
7749 
7750             long function() @property propGetterFirstFuncPtr() @property;
7751             void propGetterFirstFuncPtr(long function() @property) @property;
7752 
7753             void propSetterFirstFuncPtr(long function() @property) @property;
7754             long function() @property propSetterFirstFuncPtr() @property;
7755 
7756             static long delegate() @property staticGetterFirstDel();
7757             static void staticGetterFirstDel(long delegate() @property);
7758 
7759             static void staticSetterFirstDel(long delegate() @property);
7760             static long delegate() @property staticSetterFirstDel();
7761 
7762             static long delegate() @property staticPropGetterFirstDel() @property;
7763             static void staticPropGetterFirstDel(long delegate() @property) @property;
7764 
7765             static void staticPropSetterFirstDel(long delegate() @property) @property;
7766             static long delegate() @property staticPropSetterFirstDel() @property;
7767         }
7768 
7769         // int[] arr1;
7770         // immutable bool[] arr2;
7771         static assert( is(SymbolType!(S.arr1) == int[]));
7772         static assert( is(PropertyType!(S.arr1) == int[]));
7773         static assert( is(typeof(S.arr1) == int[]));
7774 
7775         static assert( is(SymbolType!(S.arr2) == immutable bool[]));
7776         static assert( is(PropertyType!(S.arr2) == immutable bool[]));
7777         static assert( is(typeof(S.arr2) == immutable bool[]));
7778 
7779         // void foo();
7780         static assert( is(SymbolType!(S.foo) == function));
7781         static assert( is(SymbolType!(S.foo) == ToFunctionType!(void function())));
7782         static assert(!__traits(compiles, PropertyType!(S.foo)));
7783         static assert( is(typeof(S.foo) == SymbolType!(S.foo)));
7784 
7785         //static void bar();
7786         static assert( is(SymbolType!(S.bar) == function));
7787         static assert( is(SymbolType!(S.bar) == ToFunctionType!(void function())));
7788         static assert(!__traits(compiles, PropertyType!(S.bar)));
7789         static assert( is(typeof(S.bar) == SymbolType!(S.bar)));
7790 
7791         // long bob();
7792         static assert( is(SymbolType!(S.bob) == function));
7793         static assert( is(SymbolType!(S.bob) == ToFunctionType!(long function())));
7794         static assert( is(PropertyType!(S.bob) == long));
7795         static assert( is(typeof(S.bob) == SymbolType!(S.bob)));
7796 
7797         // void sally(long);
7798         static assert( is(SymbolType!(S.sally) == function));
7799         static assert( is(SymbolType!(S.sally) == ToFunctionType!(void function(long))));
7800         static assert(!__traits(compiles, PropertyType!(S.sally)));
7801         static assert( is(typeof(S.sally) == SymbolType!(S.sally)));
7802 
7803         // @property long propGetter();
7804         static assert( is(SymbolType!(S.propGetter) == function));
7805         static assert( is(SymbolType!(S.propGetter) == ToFunctionType!(long function() @property)));
7806         static assert( is(PropertyType!(S.propGetter) == long));
7807         static assert( is(typeof(S.propGetter) == PropertyType!(S.propGetter)));
7808 
7809         // @property void propSetter(int[]);
7810         static assert( is(SymbolType!(S.propSetter) == function));
7811         static assert( is(SymbolType!(S.propSetter) == ToFunctionType!(void function(int[]) @property)));
7812         static assert(!__traits(compiles, PropertyType!(S.propSetter)));
7813         static assert(!__traits(compiles, typeof(S.propSetter)));
7814 
7815         // static @property long staticPropGetter();
7816         static assert( is(SymbolType!(S.staticPropGetter) == function));
7817         static assert( is(SymbolType!(S.staticPropGetter) == ToFunctionType!(long function() @property)));
7818         static assert( is(PropertyType!(S.staticPropGetter) == long));
7819         static assert( is(typeof(S.staticPropGetter) == PropertyType!(S.staticPropGetter)));
7820 
7821         // static @property void staticPropSetter(int[]);
7822         static assert( is(SymbolType!(S.staticPropSetter) == function));
7823         static assert( is(SymbolType!(S.staticPropSetter) == ToFunctionType!(void function(int[]) @property)));
7824         static assert(!__traits(compiles, PropertyType!(S.staticPropSetter)));
7825         static assert(!__traits(compiles, typeof(S.staticPropSetter)));
7826 
7827         // void func1();
7828         // void func1(int[]);
7829         // long func1(int[], long);
7830         {
7831             static assert( is(SymbolType!(S.func1) == ToFunctionType!(void function())));
7832             static assert(!__traits(compiles, PropertyType!(S.func1)));
7833             static assert( is(typeof((S.func1)) == SymbolType!(S.func1)));
7834 
7835             alias overloads = __traits(getOverloads, S, "func1");
7836             static assert(overloads.length == 3);
7837 
7838             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function())));
7839             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7840             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7841 
7842             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int[]))));
7843             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7844             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7845 
7846             static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(long function(int[], long))));
7847             static assert(!__traits(compiles, PropertyType!(overloads[2])));
7848             static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2])));
7849         }
7850 
7851         // long func2();
7852         // long func2(int[]);
7853         // int[] func2(int[], long);
7854         {
7855             static assert( is(SymbolType!(S.func2) == ToFunctionType!(long function())));
7856             static assert( is(PropertyType!(S.func2) == long));
7857             static assert( is(typeof((S.func2)) == SymbolType!(S.func2)));
7858 
7859             alias overloads = __traits(getOverloads, S, "func2");
7860             static assert(overloads.length == 3);
7861 
7862             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function())));
7863             static assert( is(PropertyType!(overloads[0]) == long));
7864             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7865 
7866             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function(int[]))));
7867             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7868             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7869 
7870             static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(int[] function(int[], long))));
7871             static assert(!__traits(compiles, PropertyType!(overloads[2])));
7872             static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2])));
7873         }
7874 
7875         // void func3(long*);
7876         // void func3(real);
7877         // int[] func3(long a = 0);
7878         {
7879             static assert( is(SymbolType!(S.func3) == ToFunctionType!(void function(long*))));
7880             static assert( is(PropertyType!(S.func3) == int[]));
7881             static assert( is(typeof((S.func3)) == SymbolType!(S.func3)));
7882 
7883             alias overloads = __traits(getOverloads, S, "func3");
7884             static assert(overloads.length == 3);
7885 
7886             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long*))));
7887             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7888             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7889 
7890             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(real))));
7891             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7892             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7893 
7894             static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(int[] function(long))));
7895             static assert( is(PropertyType!(overloads[2]) == int[]));
7896             static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2])));
7897         }
7898 
7899         // long getterFirst();
7900         // void getterFirst(long);
7901         {
7902             static assert( is(SymbolType!(S.getterFirst) == ToFunctionType!(long function())));
7903             static assert( is(PropertyType!(S.getterFirst) == long));
7904             static assert( is(typeof((S.getterFirst)) == SymbolType!(S.getterFirst)));
7905 
7906             alias overloads = __traits(getOverloads, S, "getterFirst");
7907             static assert(overloads.length == 2);
7908 
7909             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function())));
7910             static assert( is(PropertyType!(overloads[0]) == long));
7911             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7912 
7913             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long))));
7914             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7915             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7916         }
7917 
7918         // void setterFirst(long);
7919         // long setterFirst();
7920         {
7921             static assert( is(SymbolType!(S.setterFirst) == ToFunctionType!(void function(long))));
7922             static assert( is(PropertyType!(S.setterFirst) == long));
7923             static assert( is(typeof((S.setterFirst)) == SymbolType!(S.setterFirst)));
7924 
7925             alias overloads = __traits(getOverloads, S, "setterFirst");
7926             static assert(overloads.length == 2);
7927 
7928             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long))));
7929             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7930             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7931 
7932             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function())));
7933             static assert( is(PropertyType!(overloads[1]) == long));
7934             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7935         }
7936 
7937         // void setterOnly(int[]);
7938         // void setterOnly(long);
7939         {
7940             static assert( is(SymbolType!(S.setterOnly) == ToFunctionType!(void function(int[]))));
7941             static assert(!__traits(compiles, PropertyType!(S.setterOnly)));
7942             static assert( is(typeof((S.setterOnly)) == SymbolType!(S.setterOnly)));
7943 
7944             alias overloads = __traits(getOverloads, S, "setterOnly");
7945             static assert(overloads.length == 2);
7946 
7947             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int[]))));
7948             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7949             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7950 
7951             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long))));
7952             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7953             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7954         }
7955 
7956         // long staticGetterFirst();
7957         // void staticGetterFirst(long);
7958         {
7959             static assert( is(SymbolType!(S.staticGetterFirst) == ToFunctionType!(long function())));
7960             static assert( is(PropertyType!(S.staticGetterFirst) == long));
7961             static assert( is(typeof((S.staticGetterFirst)) == SymbolType!(S.staticGetterFirst)));
7962 
7963             alias overloads = __traits(getOverloads, S, "staticGetterFirst");
7964             static assert(overloads.length == 2);
7965 
7966             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function())));
7967             static assert( is(PropertyType!(overloads[0]) == long));
7968             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7969 
7970             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long))));
7971             static assert(!__traits(compiles, PropertyType!(overloads[1])));
7972             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7973         }
7974 
7975         // void staticSetterFirst(long);
7976         // long staticSetterFirst();
7977         {
7978             static assert( is(SymbolType!(S.staticSetterFirst) == ToFunctionType!(void function(long))));
7979             static assert( is(PropertyType!(S.staticSetterFirst) == long));
7980             static assert( is(typeof((S.staticSetterFirst)) == SymbolType!(S.staticSetterFirst)));
7981 
7982             alias overloads = __traits(getOverloads, S, "staticSetterFirst");
7983             static assert(overloads.length == 2);
7984 
7985             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long))));
7986             static assert(!__traits(compiles, PropertyType!(overloads[0])));
7987             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
7988 
7989             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function())));
7990             static assert( is(PropertyType!(overloads[1]) == long));
7991             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
7992         }
7993 
7994         // void staticSetterOnly(int[]);
7995         // void staticSetterOnly(long);
7996         {
7997             static assert( is(SymbolType!(S.staticSetterOnly) == ToFunctionType!(void function(int[]))));
7998             static assert(!__traits(compiles, PropertyType!(S.staticSetterOnly)));
7999             static assert( is(typeof((S.staticSetterOnly)) == SymbolType!(S.staticSetterOnly)));
8000 
8001             alias overloads = __traits(getOverloads, S, "staticSetterOnly");
8002             static assert(overloads.length == 2);
8003 
8004             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int[]))));
8005             static assert(!__traits(compiles, PropertyType!(overloads[0])));
8006             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8007 
8008             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long))));
8009             static assert(!__traits(compiles, PropertyType!(overloads[1])));
8010             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8011         }
8012 
8013         // @property long propGetterFirst();
8014         // @property void propGetterFirst(long);
8015         {
8016             static assert( is(SymbolType!(S.propGetterFirst) == ToFunctionType!(long function() @property)));
8017             static assert( is(PropertyType!(S.propGetterFirst) == long));
8018             static assert( is(typeof((S.propGetterFirst)) == PropertyType!(S.propGetterFirst)));
8019 
8020             alias overloads = __traits(getOverloads, S, "propGetterFirst");
8021             static assert(overloads.length == 2);
8022 
8023             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function() @property)));
8024             static assert( is(PropertyType!(overloads[0]) == long));
8025             static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
8026 
8027             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long) @property)));
8028             static assert(!__traits(compiles, PropertyType!(overloads[1])));
8029             static assert(!__traits(compiles, typeof((overloads[1]))));
8030         }
8031 
8032         // @property void propSetterFirst(long);
8033         // @property long propSetterFirst();
8034         {
8035             static assert( is(SymbolType!(S.propSetterFirst) == ToFunctionType!(void function(long) @property)));
8036             static assert( is(PropertyType!(S.propSetterFirst) == long));
8037             static assert( is(typeof((S.propSetterFirst)) == PropertyType!(S.propSetterFirst)));
8038 
8039             alias overloads = __traits(getOverloads, S, "propSetterFirst");
8040             static assert(overloads.length == 2);
8041 
8042             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long) @property)));
8043             static assert(!__traits(compiles, PropertyType!(overloads[0])));
8044             static assert(!__traits(compiles, typeof(overloads[0])));
8045 
8046             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function() @property)));
8047             static assert( is(PropertyType!(overloads[1]) == long));
8048             static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
8049         }
8050 
8051         // @property void propSetterOnly(int[]);
8052         // @property void propSetterOnly(long);
8053         {
8054             static assert( is(SymbolType!(S.propSetterOnly) == ToFunctionType!(void function(int[]) @property)));
8055             static assert(!__traits(compiles, PropertyType!(S.propSetterOnly)));
8056             static assert(!__traits(compiles, typeof((S.propSetterOnly))));
8057 
8058             alias overloads = __traits(getOverloads, S, "propSetterOnly");
8059             static assert(overloads.length == 2);
8060 
8061             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int[]) @property)));
8062             static assert(!__traits(compiles, PropertyType!(overloads[0])));
8063             static assert(!__traits(compiles, typeof(overloads[0])));
8064 
8065             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long) @property)));
8066             static assert(!__traits(compiles, PropertyType!(overloads[1])));
8067             static assert(!__traits(compiles, typeof(overloads[1])));
8068         }
8069 
8070         // @property long staticPropGetterFirst();
8071         // @property void staticPropGetterFirst(long);
8072         {
8073             static assert( is(SymbolType!(S.staticPropGetterFirst) == ToFunctionType!(long function() @property)));
8074             static assert( is(PropertyType!(S.staticPropGetterFirst) == long));
8075             static assert( is(typeof((S.staticPropGetterFirst)) == PropertyType!(S.staticPropGetterFirst)));
8076 
8077             alias overloads = __traits(getOverloads, S, "staticPropGetterFirst");
8078             static assert(overloads.length == 2);
8079 
8080             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function() @property)));
8081             static assert( is(PropertyType!(overloads[0]) == long));
8082             static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
8083 
8084             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long) @property)));
8085             static assert(!__traits(compiles, PropertyType!(overloads[1])));
8086             static assert(!__traits(compiles, typeof((overloads[1]))));
8087         }
8088 
8089         // @property void staticPropSetterFirst(long);
8090         // @property long staticPropSetterFirst();
8091         {
8092             static assert( is(SymbolType!(S.staticPropSetterFirst) == ToFunctionType!(void function(long) @property)));
8093             static assert( is(PropertyType!(S.staticPropSetterFirst) == long));
8094             static assert( is(typeof((S.staticPropSetterFirst)) == PropertyType!(S.staticPropSetterFirst)));
8095 
8096             alias overloads = __traits(getOverloads, S, "staticPropSetterFirst");
8097             static assert(overloads.length == 2);
8098 
8099             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long) @property)));
8100             static assert(!__traits(compiles, PropertyType!(overloads[0])));
8101             static assert(!__traits(compiles, typeof(overloads[0])));
8102 
8103             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function() @property)));
8104             static assert( is(PropertyType!(overloads[1]) == long));
8105             static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
8106         }
8107 
8108         // @property void staticPropSetterOnly(int[]);
8109         // @property void staticPropSetterOnly(long);
8110         {
8111             static assert( is(SymbolType!(S.staticPropSetterOnly) == ToFunctionType!(void function(int[]) @property)));
8112             static assert(!__traits(compiles, PropertyType!(S.staticPropSetterOnly)));
8113             static assert(!__traits(compiles, typeof((S.staticPropSetterOnly))));
8114 
8115             alias overloads = __traits(getOverloads, S, "staticPropSetterOnly");
8116             static assert(overloads.length == 2);
8117 
8118             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int[]) @property)));
8119             static assert(!__traits(compiles, PropertyType!(overloads[0])));
8120             static assert(!__traits(compiles, typeof(overloads[0])));
8121 
8122             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long) @property)));
8123             static assert(!__traits(compiles, PropertyType!(overloads[1])));
8124             static assert(!__traits(compiles, typeof(overloads[1])));
8125         }
8126 
8127         // long function() @property getterFirstFuncPtr();
8128         // void getterFirstFuncPtr(long function() @property);
8129         {
8130             static assert( is(SymbolType!(S.getterFirstFuncPtr) ==
8131                               ToFunctionType!(long function() @property function())));
8132             static assert( is(PropertyType!(S.getterFirstFuncPtr) == long function() @property));
8133             static assert( is(typeof((S.getterFirstFuncPtr)) == SymbolType!(S.getterFirstFuncPtr)));
8134 
8135             alias overloads = __traits(getOverloads, S, "getterFirstFuncPtr");
8136             static assert(overloads.length == 2);
8137 
8138             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function() @property function())));
8139             static assert( is(PropertyType!(overloads[0]) == long function() @property));
8140             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8141 
8142             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long function() @property))));
8143             static assert(!__traits(compiles, PropertyType!(overloads[1])));
8144             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8145         }
8146 
8147         // void setterFirstFuncPtr(long function() @property);
8148         // long function() @property setterFirstFuncPtr();
8149         {
8150             static assert( is(SymbolType!(S.setterFirstFuncPtr) ==
8151                               ToFunctionType!(void function(long function() @property))));
8152             static assert( is(PropertyType!(S.setterFirstFuncPtr) == long function() @property));
8153             static assert( is(typeof((S.setterFirstFuncPtr)) == SymbolType!(S.setterFirstFuncPtr)));
8154 
8155             alias overloads = __traits(getOverloads, S, "setterFirstFuncPtr");
8156             static assert(overloads.length == 2);
8157 
8158             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long function() @property))));
8159             static assert(!__traits(compiles, PropertyType!(overloads[0])));
8160             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8161 
8162             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function() @property function())));
8163             static assert( is(PropertyType!(overloads[1]) == long function() @property));
8164             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8165         }
8166 
8167         // long function() @property propGetterFirstFuncPtr() @property;
8168         // void propGetterFirstFuncPtr(long function() @property) @property;
8169         {
8170             static assert( is(SymbolType!(S.propGetterFirstFuncPtr) ==
8171                               ToFunctionType!(long function() @property function() @property)));
8172             static assert( is(PropertyType!(S.propGetterFirstFuncPtr) == long function() @property));
8173             static assert( is(typeof((S.propGetterFirstFuncPtr)) == PropertyType!(S.propGetterFirstFuncPtr)));
8174 
8175             alias overloads = __traits(getOverloads, S, "propGetterFirstFuncPtr");
8176             static assert(overloads.length == 2);
8177 
8178             static assert( is(SymbolType!(overloads[0]) ==
8179                               ToFunctionType!(long function() @property function() @property)));
8180             static assert( is(PropertyType!(overloads[0]) == long function() @property));
8181             static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
8182 
8183             static assert( is(SymbolType!(overloads[1]) ==
8184                               ToFunctionType!(void function(long function() @property) @property)));
8185             static assert(!__traits(compiles, PropertyType!(overloads[1])));
8186             static assert(!__traits(compiles, typeof((overloads[1]))));
8187         }
8188 
8189         // void propSetterFirstFuncPtr(long function() @property) @property;
8190         // long function() @property propSetterFirstFuncPtr() @property;
8191         {
8192             static assert( is(SymbolType!(S.propSetterFirstFuncPtr) ==
8193                               ToFunctionType!(void function(long function() @property) @property)));
8194             static assert( is(PropertyType!(S.propSetterFirstFuncPtr) == long function() @property));
8195             static assert( is(typeof((S.propSetterFirstFuncPtr)) == PropertyType!(S.propSetterFirstFuncPtr)));
8196 
8197             alias overloads = __traits(getOverloads, S, "propSetterFirstFuncPtr");
8198             static assert(overloads.length == 2);
8199 
8200             static assert( is(SymbolType!(overloads[0]) ==
8201                               ToFunctionType!(void function(long function() @property) @property)));
8202             static assert(!__traits(compiles, PropertyType!(overloads[0])));
8203             static assert(!__traits(compiles, typeof(overloads[0])));
8204 
8205             static assert( is(SymbolType!(overloads[1]) ==
8206                               ToFunctionType!(long function() @property function() @property)));
8207             static assert( is(PropertyType!(overloads[1]) == long function() @property));
8208             static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
8209         }
8210 
8211         // long function() @property staticGetterFirstDel();
8212         // void staticGetterFirstDel(long function() @property);
8213         {
8214             static assert( is(SymbolType!(S.staticGetterFirstDel) ==
8215                               ToFunctionType!(long delegate() @property function())));
8216             static assert( is(PropertyType!(S.staticGetterFirstDel) == long delegate() @property));
8217             static assert( is(typeof((S.staticGetterFirstDel)) == SymbolType!(S.staticGetterFirstDel)));
8218 
8219             alias overloads = __traits(getOverloads, S, "staticGetterFirstDel");
8220             static assert(overloads.length == 2);
8221 
8222             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long delegate() @property function())));
8223             static assert( is(PropertyType!(overloads[0]) == long delegate() @property));
8224             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8225 
8226             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long delegate() @property))));
8227             static assert(!__traits(compiles, PropertyType!(overloads[1])));
8228             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8229         }
8230 
8231         // void setterFirstDel(long function() @property);
8232         // long function() @property setterFirstDel();
8233         {
8234             static assert( is(SymbolType!(S.staticSetterFirstDel) ==
8235                               ToFunctionType!(void function(long delegate() @property))));
8236             static assert( is(PropertyType!(S.staticSetterFirstDel) == long delegate() @property));
8237             static assert( is(typeof((S.staticSetterFirstDel)) == SymbolType!(S.staticSetterFirstDel)));
8238 
8239             alias overloads = __traits(getOverloads, S, "staticSetterFirstDel");
8240             static assert(overloads.length == 2);
8241 
8242             static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long delegate() @property))));
8243             static assert(!__traits(compiles, PropertyType!(overloads[0])));
8244             static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8245 
8246             static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long delegate() @property function())));
8247             static assert( is(PropertyType!(overloads[1]) == long delegate() @property));
8248             static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8249         }
8250 
8251         // long function() @property staticPropGetterFirstDel() @property;
8252         // void staticPropGetterFirstDel(long function() @property) @property;
8253         {
8254             static assert( is(SymbolType!(S.staticPropGetterFirstDel) ==
8255                               ToFunctionType!(long delegate() @property function() @property)));
8256             static assert( is(PropertyType!(S.staticPropGetterFirstDel) == long delegate() @property));
8257             static assert( is(typeof((S.staticPropGetterFirstDel)) == PropertyType!(S.staticPropGetterFirstDel)));
8258 
8259             alias overloads = __traits(getOverloads, S, "staticPropGetterFirstDel");
8260             static assert(overloads.length == 2);
8261 
8262             static assert( is(SymbolType!(overloads[0]) ==
8263                               ToFunctionType!(long delegate() @property function() @property)));
8264             static assert( is(PropertyType!(overloads[0]) == long delegate() @property));
8265             static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
8266 
8267             static assert( is(SymbolType!(overloads[1]) ==
8268                               ToFunctionType!(void function(long delegate() @property) @property)));
8269             static assert(!__traits(compiles, PropertyType!(overloads[1])));
8270             static assert(!__traits(compiles, typeof((overloads[1]))));
8271         }
8272 
8273         // void propSetterFirstDel(long function() @property) @property;
8274         // long function() @property propSetterFirstDel() @property;
8275         {
8276             static assert( is(SymbolType!(S.staticPropSetterFirstDel) ==
8277                               ToFunctionType!(void function(long delegate() @property) @property)));
8278             static assert( is(PropertyType!(S.staticPropSetterFirstDel) == long delegate() @property));
8279             static assert( is(typeof((S.staticPropSetterFirstDel)) == PropertyType!(S.staticPropSetterFirstDel)));
8280 
8281             alias overloads = __traits(getOverloads, S, "staticPropSetterFirstDel");
8282             static assert(overloads.length == 2);
8283 
8284             static assert( is(SymbolType!(overloads[0]) ==
8285                               ToFunctionType!(void function(long delegate() @property) @property)));
8286             static assert(!__traits(compiles, PropertyType!(overloads[0])));
8287             static assert(!__traits(compiles, typeof(overloads[0])));
8288 
8289             static assert( is(SymbolType!(overloads[1]) ==
8290                               ToFunctionType!(long delegate() @property function() @property)));
8291             static assert( is(PropertyType!(overloads[1]) == long delegate() @property));
8292             static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
8293         }
8294     }
8295     {
8296         static interface I
8297         {
8298             void foo();
8299             static void bar();
8300 
8301             int func1();
8302             void func1(int);
8303 
8304             void func2(int);
8305             int func2();
8306 
8307             @property void prop1(int);
8308             @property int prop1();
8309 
8310             @property int prop2();
8311             @property void prop2(int);
8312 
8313             static @property string staticProp();
8314             static @property void staticProp(real);
8315 
8316             @property void extraProp(string);
8317 
8318             int defaultArg1(string str = "foo");
8319             void defaultArg1(int, string str = "foo");
8320 
8321             void defaultArg2(int, string str = "foo");
8322             int defaultArg2(string str = "foo");
8323 
8324             @property int defaultArgProp1(string str = "foo");
8325             @property void defaultArgProp1(int, string str = "foo");
8326 
8327             @property void defaultArgProp2(int, string str = "foo");
8328             @property int defaultArgProp2(string str = "foo");
8329 
8330             string defaultArgInDerived1(int);
8331             void defaultArgInDerived1(string, int);
8332 
8333             void defaultArgInDerived2(string, int);
8334             string defaultArgInDerived2(int);
8335 
8336             @property string defaultArgInDerivedProp1(int);
8337             @property void defaultArgInDerivedProp1(string, int);
8338 
8339             @property void defaultArgInDerivedProp2(string, int);
8340             @property string defaultArgInDerivedProp2(int);
8341         }
8342 
8343         {
8344             // void foo()
8345             static assert( is(SymbolType!(I.foo) == ToFunctionType!(void function())));
8346             static assert(!__traits(compiles, PropertyType!(I.foo)));
8347             static assert( is(typeof(I.foo) == SymbolType!(I.foo)));
8348 
8349             // static void bar()
8350             static assert( is(SymbolType!(I.bar) == ToFunctionType!(void function())));
8351             static assert(!__traits(compiles, PropertyType!(I.bar)));
8352             static assert( is(typeof(I.bar) == SymbolType!(I.bar)));
8353 
8354             // int func1();
8355             // void func1(int);
8356             {
8357                 static assert( is(SymbolType!(I.func1) == ToFunctionType!(int function())));
8358                 static assert( is(PropertyType!(I.func1) == int));
8359                 static assert( is(typeof(I.func1) == SymbolType!(I.func1)));
8360 
8361                 alias overloads = __traits(getOverloads, I, "func1");
8362                 static assert(overloads.length == 2);
8363 
8364                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function())));
8365                 static assert( is(PropertyType!(overloads[0]) == int));
8366                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8367 
8368                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int))));
8369                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8370                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8371             }
8372 
8373             // void func2(int);
8374             // int func2();
8375             {
8376                 static assert( is(SymbolType!(I.func2) == ToFunctionType!(void function(int))));
8377                 static assert( is(PropertyType!(I.func2) == int));
8378                 static assert( is(typeof(I.func2) == SymbolType!(I.func2)));
8379 
8380                 alias overloads = __traits(getOverloads, I, "func2");
8381                 static assert(overloads.length == 2);
8382 
8383                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int))));
8384                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8385                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8386 
8387                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function())));
8388                 static assert( is(PropertyType!(overloads[1]) == int));
8389                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8390             }
8391 
8392             // @property void prop1(int);
8393             // @property int prop1();
8394             {
8395                 static assert( is(SymbolType!(I.prop1) == ToFunctionType!(void function(int) @property)));
8396                 static assert( is(PropertyType!(I.prop1) == int));
8397                 static assert( is(typeof(I.prop1) == PropertyType!(I.prop1)));
8398 
8399                 alias overloads = __traits(getOverloads, I, "prop1");
8400                 static assert(overloads.length == 2);
8401 
8402                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(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!(int function() @property)));
8407                 static assert( is(PropertyType!(overloads[1]) == int));
8408                 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
8409             }
8410 
8411             // @property int prop2();
8412             // @property void prop2(int);
8413             {
8414                 static assert( is(SymbolType!(I.prop2) == ToFunctionType!(int function() @property)));
8415                 static assert( is(PropertyType!(I.prop2) == int));
8416                 static assert( is(typeof(I.prop2) == PropertyType!(I.prop2)));
8417 
8418                 alias overloads = __traits(getOverloads, I, "prop2");
8419                 static assert(overloads.length == 2);
8420 
8421                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function() @property)));
8422                 static assert( is(PropertyType!(overloads[0]) == int));
8423                 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
8424 
8425                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int) @property)));
8426                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8427                 static assert(!__traits(compiles, typeof(overloads[1])));
8428             }
8429 
8430             // static @property string staticProp();
8431             // static @property void staticProp(real);
8432             {
8433                 static assert( is(SymbolType!(I.staticProp) == ToFunctionType!(string function() @property)));
8434                 static assert( is(PropertyType!(I.staticProp) == string));
8435                 static assert( is(typeof(I.staticProp) == PropertyType!(I.staticProp)));
8436 
8437                 alias overloads = __traits(getOverloads, I, "staticProp");
8438                 static assert(overloads.length == 2);
8439 
8440                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function() @property)));
8441                 static assert( is(PropertyType!(overloads[0]) == string));
8442                 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
8443 
8444                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(real) @property)));
8445                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8446                 static assert(!__traits(compiles, typeof(overloads[1])));
8447             }
8448 
8449             // @property void extraProp(string);
8450             {
8451                 static assert( is(SymbolType!(I.extraProp) == ToFunctionType!(void function(string) @property)));
8452                 static assert(!__traits(compiles, PropertyType!(I.extraProp)));
8453                 static assert(!__traits(compiles, typeof(I.extraProp)));
8454 
8455                 alias overloads = __traits(getOverloads, I, "extraProp");
8456                 static assert(overloads.length == 1);
8457 
8458                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string) @property)));
8459                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8460                 static assert(!__traits(compiles, typeof(overloads[0])));
8461             }
8462 
8463             // int defaultArg1(string str = "foo");
8464             // void defaultArg1(int, string str = "foo");
8465             {
8466                 static assert( is(SymbolType!(I.defaultArg1) == ToFunctionType!(int function(string))));
8467                 static assert( is(PropertyType!(I.defaultArg1) == int));
8468                 static assert( is(typeof(I.defaultArg1) == SymbolType!(I.defaultArg1)));
8469 
8470                 alias overloads = __traits(getOverloads, I, "defaultArg1");
8471                 static assert(overloads.length == 2);
8472 
8473                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string))));
8474                 static assert( is(PropertyType!(overloads[0]) == int));
8475                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8476 
8477                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string))));
8478                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8479                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8480             }
8481 
8482             // void defaultArg2(int, string str = "foo");
8483             // int defaultArg2(string str = "foo");
8484             {
8485                 static assert( is(SymbolType!(I.defaultArg2) == ToFunctionType!(void function(int, string))));
8486                 static assert( is(PropertyType!(I.defaultArg2) == int));
8487                 static assert( is(typeof(I.defaultArg2) == SymbolType!(I.defaultArg2)));
8488 
8489                 alias overloads = __traits(getOverloads, I, "defaultArg2");
8490                 static assert(overloads.length == 2);
8491 
8492                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string))));
8493                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8494                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8495 
8496                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string))));
8497                 static assert( is(PropertyType!(overloads[1]) == int));
8498                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8499             }
8500 
8501             // @property int defaultArgProp1(string str = "foo");
8502             // @property void defaultArgProp1(int, string str = "foo");
8503             {
8504                 static assert( is(SymbolType!(I.defaultArgProp1) == ToFunctionType!(int function(string) @property)));
8505                 static assert( is(PropertyType!(I.defaultArgProp1) == int));
8506                 static assert( is(typeof(I.defaultArgProp1) == PropertyType!(I.defaultArgProp1)));
8507 
8508                 alias overloads = __traits(getOverloads, I, "defaultArgProp1");
8509                 static assert(overloads.length == 2);
8510 
8511                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string) @property)));
8512                 static assert( is(PropertyType!(overloads[0]) == int));
8513                 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
8514 
8515                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string) @property)));
8516                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8517                 static assert(!__traits(compiles, typeof(overloads[1])));
8518             }
8519 
8520             // @property void defaultArgProp2(int, string str = "foo");
8521             // @property int defaultArgProp2(string str = "foo");
8522             {
8523                 static assert( is(SymbolType!(I.defaultArgProp2) ==
8524                                   ToFunctionType!(void function(int, string) @property)));
8525                 static assert( is(PropertyType!(I.defaultArgProp2) == int));
8526                 static assert( is(typeof(I.defaultArgProp2) == PropertyType!(I.defaultArgProp2)));
8527 
8528                 alias overloads = __traits(getOverloads, I, "defaultArgProp2");
8529                 static assert(overloads.length == 2);
8530 
8531                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string) @property)));
8532                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8533                 static assert(!__traits(compiles, typeof(overloads[0])));
8534 
8535                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string) @property)));
8536                 static assert( is(PropertyType!(overloads[1]) == int));
8537                 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
8538             }
8539 
8540             // string defaultArgInDerived1(int);
8541             // void defaultArgInDerived1(string, int);
8542             {
8543                 static assert( is(SymbolType!(I.defaultArgInDerived1) == ToFunctionType!(string function(int))));
8544                 static assert(!__traits(compiles, PropertyType!(I.defaultArgInDerived1)));
8545                 static assert( is(typeof(I.defaultArgInDerived1) == SymbolType!(I.defaultArgInDerived1)));
8546 
8547                 alias overloads = __traits(getOverloads, I, "defaultArgInDerived1");
8548                 static assert(overloads.length == 2);
8549 
8550                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int))));
8551                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8552                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8553 
8554                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int))));
8555                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8556                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8557             }
8558 
8559             // void defaultArgInDerived2(string, int);
8560             // string defaultArgInDerived2(int);
8561             {
8562                 static assert( is(SymbolType!(I.defaultArgInDerived2) == ToFunctionType!(void function(string, int))));
8563                 static assert(!__traits(compiles, PropertyType!(I.defaultArgInDerived2)));
8564                 static assert( is(typeof(I.defaultArgInDerived2) == SymbolType!(I.defaultArgInDerived2)));
8565 
8566                 alias overloads = __traits(getOverloads, I, "defaultArgInDerived2");
8567                 static assert(overloads.length == 2);
8568 
8569                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int))));
8570                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8571                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8572 
8573                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int))));
8574                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8575                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8576             }
8577 
8578             // @property string defaultArgInDerivedProp1(int);
8579             // @property void defaultArgInDerivedProp1(string, int);
8580             {
8581                 static assert( is(SymbolType!(I.defaultArgInDerivedProp1) ==
8582                                   ToFunctionType!(string function(int) @property)));
8583                 static assert(!__traits(compiles, PropertyType!(I.defaultArgInDerivedProp1)));
8584                 static assert(!__traits(compiles, typeof(I.defaultArgInDerivedProp1)));
8585 
8586                 alias overloads = __traits(getOverloads, I, "defaultArgInDerivedProp1");
8587                 static assert(overloads.length == 2);
8588 
8589                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int) @property)));
8590                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8591                 static assert(!__traits(compiles, typeof(overloads[0])));
8592 
8593                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int) @property)));
8594                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8595                 static assert(!__traits(compiles, typeof(overloads[0])));
8596             }
8597 
8598             // @property void defaultArgInDerivedProp2(string, int);
8599             // @property string defaultArgInDerivedProp2(int);
8600             {
8601                 static assert( is(SymbolType!(I.defaultArgInDerivedProp2) ==
8602                                   ToFunctionType!(void function(string, int) @property)));
8603                 static assert(!__traits(compiles, PropertyType!(I.defaultArgInDerivedProp2)));
8604                 static assert(!__traits(compiles, typeof(I.defaultArgInDerivedProp2)));
8605 
8606                 alias overloads = __traits(getOverloads, I, "defaultArgInDerivedProp2");
8607                 static assert(overloads.length == 2);
8608 
8609                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int) @property)));
8610                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8611                 static assert(!__traits(compiles, typeof(overloads[0])));
8612 
8613                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int) @property)));
8614                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8615                 static assert(!__traits(compiles, typeof(overloads[1])));
8616             }
8617         }
8618 
8619         // For whatever reason, the virtual functions have to have bodies, or
8620         // the linker complains, even though the functions aren't actually
8621         // called anywhere, but having them implement the functions which are in
8622         // the interface at least gets rid of the attribute inference.
8623         static class C1 : I
8624         {
8625             shared int i;
8626             string s;
8627 
8628             override void foo() {}
8629 
8630             // This shadows the one in the interface, and it has a different
8631             // signature, so it makes sure that we're getting the right one.
8632             static int bar();
8633 
8634             final void baz();
8635 
8636             override int func1() { return 0; }
8637             override void func1(int) {}
8638 
8639             override void func2(int) {}
8640             override int func2() { return 0; }
8641 
8642             override @property void prop1(int) {}
8643             override @property int prop1() { return 0; }
8644 
8645             override @property int prop2() { return 0; }
8646             override @property void prop2(int) {}
8647 
8648             override @property void extraProp(string) {}
8649             @property bool extraProp() { return true; }
8650 
8651             override int defaultArg1(string str = "foo") { return 42; }
8652             override void defaultArg1(int, string str = "foo") {}
8653 
8654             // This tests the case where the derived type doesn't provide
8655             // default arguments even though the interface does.
8656             override void defaultArg2(int, string str) {}
8657             override int defaultArg2(string str) { return 42; }
8658 
8659             override @property int defaultArgProp1(string str = "foo") { return 42; }
8660             override @property void defaultArgProp1(int, string str = "foo") {}
8661 
8662             // This tests the case where the derived type doesn't provide
8663             // default arguments even though the interface does.
8664             override @property void defaultArgProp2(int, string str) {}
8665             override @property int defaultArgProp2(string str) { return 42; }
8666 
8667             override string defaultArgInDerived1(int i = 0) { return ""; }
8668             override void defaultArgInDerived1(string, int i = 0) {}
8669 
8670             override void defaultArgInDerived2(string, int i = 0) {}
8671             override string defaultArgInDerived2(int i = 0) { return ""; }
8672 
8673             @property string defaultArgInDerivedProp1(int i = 0) { return ""; }
8674             @property void defaultArgInDerivedProp1(string, int i = 0) {}
8675 
8676             @property void defaultArgInDerivedProp2(string, int i = 0) {}
8677             @property string defaultArgInDerivedProp2(int i = 0) { return ""; }
8678         }
8679 
8680         {
8681             // shared int i;
8682             // string s;
8683             static assert( is(SymbolType!(C1.i) == shared int));
8684             static assert( is(PropertyType!(C1.i) == shared int));
8685             static assert( is(typeof(C1.i) == shared int));
8686 
8687             static assert( is(SymbolType!(C1.s) == string));
8688             static assert( is(PropertyType!(C1.s) == string));
8689             static assert( is(typeof(C1.s) == string));
8690 
8691             // override void foo()
8692             static assert( is(SymbolType!(C1.foo) == ToFunctionType!(void function())));
8693             static assert(!__traits(compiles, PropertyType!(C1.foo)));
8694             static assert( is(typeof(C1.foo) == SymbolType!(C1.foo)));
8695 
8696             // static int bar()
8697             static assert( is(SymbolType!(C1.bar) == ToFunctionType!(int function())));
8698             static assert( is(PropertyType!(C1.bar) == int));
8699             static assert( is(typeof(C1.bar) == SymbolType!(C1.bar)));
8700 
8701             // void baz()
8702             static assert( is(SymbolType!(C1.baz) == ToFunctionType!(void function())));
8703             static assert(!__traits(compiles, PropertyType!(C1.baz)));
8704             static assert( is(typeof(C1.baz) == SymbolType!(C1.baz)));
8705 
8706             // override int func1();
8707             // override void func1(int);
8708             {
8709                 static assert( is(SymbolType!(C1.func1) == ToFunctionType!(int function())));
8710                 static assert( is(PropertyType!(C1.func1) == int));
8711                 static assert( is(typeof(C1.func1) == SymbolType!(C1.func1)));
8712 
8713                 alias overloads = __traits(getOverloads, C1, "func1");
8714                 static assert(overloads.length == 2);
8715 
8716                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function())));
8717                 static assert( is(PropertyType!(overloads[0]) == int));
8718                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8719 
8720                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int))));
8721                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8722                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8723             }
8724 
8725             // override void func2(int);
8726             // override int func2();
8727             {
8728                 static assert( is(SymbolType!(C1.func2) == ToFunctionType!(void function(int))));
8729                 static assert( is(PropertyType!(C1.func2) == int));
8730                 static assert( is(typeof(C1.func2) == SymbolType!(C1.func2)));
8731 
8732                 alias overloads = __traits(getOverloads, C1, "func2");
8733                 static assert(overloads.length == 2);
8734 
8735                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int))));
8736                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8737                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8738 
8739                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function())));
8740                 static assert( is(PropertyType!(overloads[1]) == int));
8741                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8742             }
8743 
8744             // override @property void prop1(int);
8745             // override @property int prop1();
8746             {
8747                 static assert( is(SymbolType!(C1.prop1) == ToFunctionType!(void function(int) @property)));
8748                 static assert( is(PropertyType!(C1.prop1) == int));
8749                 static assert( is(typeof(C1.prop1) == PropertyType!(C1.prop1)));
8750 
8751                 alias overloads = __traits(getOverloads, C1, "prop1");
8752                 static assert(overloads.length == 2);
8753 
8754                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property)));
8755                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8756                 static assert(!__traits(compiles, typeof(overloads[0])));
8757 
8758                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property)));
8759                 static assert( is(PropertyType!(overloads[1]) == int));
8760                 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
8761             }
8762 
8763             // override @property int prop2();
8764             // override @property void prop2(int);
8765             {
8766                 static assert( is(SymbolType!(C1.prop2) == ToFunctionType!(int function() @property)));
8767                 static assert( is(PropertyType!(C1.prop2) == int));
8768                 static assert( is(typeof(C1.prop2) == PropertyType!(C1.prop2)));
8769 
8770                 alias overloads = __traits(getOverloads, C1, "prop2");
8771                 static assert(overloads.length == 2);
8772 
8773                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function() @property)));
8774                 static assert( is(PropertyType!(overloads[0]) == int));
8775                 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
8776 
8777                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int) @property)));
8778                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8779                 static assert(!__traits(compiles, typeof(overloads[1])));
8780             }
8781 
8782             // Actually on I, not C1.
8783             // static @property string staticProp();
8784             // static @property void staticProp(real);
8785             {
8786                 static assert( is(SymbolType!(C1.staticProp) == ToFunctionType!(string function() @property)));
8787                 static assert( is(PropertyType!(C1.staticProp) == string));
8788                 static assert( is(typeof(C1.staticProp) == PropertyType!(C1.staticProp)));
8789 
8790                 alias overloads = __traits(getOverloads, C1, "staticProp");
8791                 static assert(overloads.length == 2);
8792 
8793                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function() @property)));
8794                 static assert( is(PropertyType!(overloads[0]) == string));
8795                 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
8796 
8797                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(real) @property)));
8798                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8799                 static assert(!__traits(compiles, typeof(overloads[1])));
8800             }
8801 
8802             // override @property void extraProp(string);
8803             // @property bool extraProp() { return true; }
8804             {
8805                 static assert( is(SymbolType!(C1.extraProp) == ToFunctionType!(void function(string) @property)));
8806                 static assert( is(PropertyType!(C1.extraProp) == bool));
8807                 static assert( is(typeof(C1.extraProp) == bool));
8808 
8809                 alias overloads = __traits(getOverloads, C1, "extraProp");
8810                 static assert(overloads.length == 2);
8811 
8812                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string) @property)));
8813                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8814                 static assert(!__traits(compiles, typeof(overloads[0])));
8815 
8816                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(bool function() @property)));
8817                 static assert( is(PropertyType!(overloads[1]) == bool));
8818                 static assert( is(typeof(overloads[1]) == bool));
8819             }
8820 
8821             // override int defaultArg1(string str = "foo");
8822             // override void defaultArg1(int, string str = "foo");
8823             {
8824                 static assert( is(SymbolType!(C1.defaultArg1) == ToFunctionType!(int function(string))));
8825                 static assert( is(PropertyType!(C1.defaultArg1) == int));
8826                 static assert( is(typeof(C1.defaultArg1) == SymbolType!(C1.defaultArg1)));
8827 
8828                 alias overloads = __traits(getOverloads, C1, "defaultArg1");
8829                 static assert(overloads.length == 2);
8830 
8831                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string))));
8832                 static assert( is(PropertyType!(overloads[0]) == int));
8833                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8834 
8835                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string))));
8836                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8837                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8838             }
8839 
8840             // I provides default arguments, but C1 does not.
8841             // override void defaultArg2(int, string);
8842             // override int defaultArg2(string);
8843             {
8844                 static assert( is(SymbolType!(C1.defaultArg2) == ToFunctionType!(void function(int, string))));
8845                 static assert(!__traits(compiles, PropertyType!(C1.defaultArg2)));
8846                 static assert( is(typeof(C1.defaultArg2) == SymbolType!(C1.defaultArg2)));
8847 
8848                 alias overloads = __traits(getOverloads, C1, "defaultArg2");
8849                 static assert(overloads.length == 2);
8850 
8851                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string))));
8852                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8853                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8854 
8855                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string))));
8856                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8857                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8858             }
8859 
8860             // override @property int defaultArgProp1(string str = "foo");
8861             // override @property void defaultArgProp1(int, string str = "foo");
8862             {
8863                 static assert( is(SymbolType!(C1.defaultArgProp1) == ToFunctionType!(int function(string) @property)));
8864                 static assert( is(PropertyType!(C1.defaultArgProp1) == int));
8865                 static assert( is(typeof(C1.defaultArgProp1) == PropertyType!(C1.defaultArgProp1)));
8866 
8867                 alias overloads = __traits(getOverloads, C1, "defaultArgProp1");
8868                 static assert(overloads.length == 2);
8869 
8870                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string) @property)));
8871                 static assert( is(PropertyType!(overloads[0]) == int));
8872                 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
8873 
8874                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string) @property)));
8875                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8876                 static assert(!__traits(compiles, typeof(overloads[1])));
8877             }
8878 
8879             // I provides default arguments, but C1 does not.
8880             // override @property void defaultArgProp2(int, string str);
8881             // override @property int defaultArgProp2(string str);
8882             {
8883                 static assert( is(SymbolType!(C1.defaultArgProp2) ==
8884                                   ToFunctionType!(void function(int, string) @property)));
8885                 static assert(!__traits(compiles, PropertyType!(C1.defaultArgProp2)));
8886                 static assert(!__traits(compiles, typeof(C1.defaultArgProp2)));
8887 
8888                 alias overloads = __traits(getOverloads, C1, "defaultArgProp2");
8889                 static assert(overloads.length == 2);
8890 
8891                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string) @property)));
8892                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8893                 static assert(!__traits(compiles, typeof(overloads[0])));
8894 
8895                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string) @property)));
8896                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8897                 static assert(!__traits(compiles, typeof(overloads[1])));
8898             }
8899 
8900             // I does not provide default arguments, but C1 does.
8901             // override string defaultArgInDerived1(int i = 0);
8902             // override void defaultArgInDerived1(string, int i = 0);
8903             {
8904                 static assert( is(SymbolType!(C1.defaultArgInDerived1) == ToFunctionType!(string function(int))));
8905                 static assert( is(PropertyType!(C1.defaultArgInDerived1) == string));
8906                 static assert( is(typeof(C1.defaultArgInDerived1) == SymbolType!(C1.defaultArgInDerived1)));
8907 
8908                 alias overloads = __traits(getOverloads, C1, "defaultArgInDerived1");
8909                 static assert(overloads.length == 2);
8910 
8911                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int))));
8912                 static assert( is(PropertyType!(overloads[0]) == string));
8913                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8914 
8915                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int))));
8916                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8917                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8918             }
8919 
8920             // I does not provide default arguments, but C1 does.
8921             // override void defaultArgInDerived2(string, int i = 0);
8922             // override string defaultArgInDerived2(int i = 0);
8923             {
8924                 static assert( is(SymbolType!(C1.defaultArgInDerived2) == ToFunctionType!(void function(string, int))));
8925                 static assert( is(PropertyType!(C1.defaultArgInDerived2) == string));
8926                 static assert( is(typeof(C1.defaultArgInDerived2) == SymbolType!(C1.defaultArgInDerived2)));
8927 
8928                 alias overloads = __traits(getOverloads, C1, "defaultArgInDerived2");
8929                 static assert(overloads.length == 2);
8930 
8931                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int))));
8932                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8933                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
8934 
8935                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int))));
8936                 static assert( is(PropertyType!(overloads[1]) == string));
8937                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
8938             }
8939 
8940             // I does not provide default arguments, but C1 does.
8941             // override @property string defaultArgInDerivedProp1(int i = 0);
8942             // override @property void defaultArgInDerivedProp1(string, int i = 0);
8943             {
8944                 static assert( is(SymbolType!(C1.defaultArgInDerivedProp1) ==
8945                                   ToFunctionType!(string function(int) @property)));
8946                 static assert( is(PropertyType!(C1.defaultArgInDerivedProp1) == string));
8947                 static assert( is(typeof(C1.defaultArgInDerivedProp1) == string));
8948 
8949                 alias overloads = __traits(getOverloads, C1, "defaultArgInDerivedProp1");
8950                 static assert(overloads.length == 2);
8951 
8952                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int) @property)));
8953                 static assert( is(PropertyType!(overloads[0]) == string));
8954                 static assert( is(typeof(overloads[0]) == string));
8955 
8956                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int) @property)));
8957                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
8958                 static assert(!__traits(compiles, typeof(overloads[1])));
8959             }
8960 
8961             // I does not provide default arguments, but C1 does.
8962             // override @property void defaultArgInDerivedProp2(string, int i = 0);
8963             // override @property string defaultArgInDerivedProp2(int i = 0);
8964             {
8965                 static assert( is(SymbolType!(C1.defaultArgInDerivedProp2) ==
8966                                   ToFunctionType!(void function(string, int) @property)));
8967                 static assert( is(PropertyType!(C1.defaultArgInDerivedProp2) == string));
8968                 static assert( is(typeof(C1.defaultArgInDerivedProp2) == string));
8969 
8970                 alias overloads = __traits(getOverloads, C1, "defaultArgInDerivedProp2");
8971                 static assert(overloads.length == 2);
8972 
8973                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int) @property)));
8974                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
8975                 static assert(!__traits(compiles, typeof(overloads[0])));
8976 
8977                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int) @property)));
8978                 static assert( is(PropertyType!(overloads[1]) == string));
8979                 static assert( is(typeof(overloads[1]) == string));
8980             }
8981         }
8982 
8983         // Changes the function order (and has different extraProps).
8984         // It also provides default arguments when C1 does not.
8985         static class C2 : I
8986         {
8987             real r;
8988             bool b;
8989             int* ptr;
8990 
8991             @property long extraProp() { return 42; }
8992             override @property void extraProp(string) {}
8993             @property void extraProp(int) {}
8994 
8995             override void foo() {}
8996 
8997             @property string defaultArgInDerivedProp2(int i = 0) { return "dlang"; }
8998             @property void defaultArgInDerivedProp2(string, int i = 0) {}
8999 
9000             string defaultArgInDerived2(int i = 0) { return "dlang"; }
9001             void defaultArgInDerived2(string, int i = 0) {}
9002 
9003             void defaultArgInDerived1(string, int i = 0) {}
9004             string defaultArgInDerived1(int i = 0) { return "dlang"; }
9005 
9006             @property void defaultArgInDerivedProp1(string, int i = 0) {}
9007             @property string defaultArgInDerivedProp1(int i = 0) { return "dlang"; }
9008 
9009             override void defaultArg2(int, string str = "bar") {}
9010             override int defaultArg2(string str = "bar") { return 0; }
9011 
9012             override @property int defaultArgProp2(string str = "bar") { return 0; }
9013             override @property void defaultArgProp2(int, string str = "bar") {}
9014 
9015             override @property void defaultArgProp1(int, string str = "bar") {}
9016             override @property int defaultArgProp1(string str = "bar") { return 0; }
9017 
9018             override void defaultArg1(int, string str = "bar") {}
9019             override int defaultArg1(string str = "bar") { return 0; }
9020 
9021             override @property void prop2(int) {}
9022             override @property int prop2() { return 0; }
9023 
9024             override @property void prop1(int) {}
9025             override @property int prop1() { return 0; }
9026 
9027             override void func2(int) {}
9028             override int func2() { return 0; }
9029 
9030             override int func1() { return 0; }
9031             override void func1(int) {}
9032         }
9033 
9034         {
9035             // real r;
9036             // bool b;
9037             // int* ptr;
9038 
9039             static assert( is(SymbolType!(C2.r) == real));
9040             static assert( is(PropertyType!(C2.r) == real));
9041             static assert( is(typeof(C2.r) == real));
9042 
9043             static assert( is(SymbolType!(C2.b) == bool));
9044             static assert( is(PropertyType!(C2.b) == bool));
9045             static assert( is(typeof(C2.b) == bool));
9046 
9047             static assert( is(SymbolType!(C2.ptr) == int*));
9048             static assert( is(PropertyType!(C2.ptr) == int*));
9049             static assert( is(typeof(C2.ptr) == int*));
9050 
9051             // Actually on I, not C2.
9052             // static @property string staticProp();
9053             // static @property void staticProp(real);
9054             {
9055                 static assert( is(SymbolType!(C2.staticProp) == ToFunctionType!(string function() @property)));
9056                 static assert( is(PropertyType!(C2.staticProp) == string));
9057                 static assert( is(typeof(C2.staticProp) == PropertyType!(C2.staticProp)));
9058 
9059                 alias overloads = __traits(getOverloads, C2, "staticProp");
9060                 static assert(overloads.length == 2);
9061 
9062                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function() @property)));
9063                 static assert( is(PropertyType!(overloads[0]) == string));
9064                 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
9065 
9066                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(real) @property)));
9067                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
9068                 static assert(!__traits(compiles, typeof(overloads[1])));
9069             }
9070 
9071             // @property long extraProp() { return 42; }
9072             // override @property void extraProp(string) {}
9073             // @property void extraProp(int) {}
9074             {
9075                 static assert( is(SymbolType!(C2.extraProp) == ToFunctionType!(long function() @property)));
9076                 static assert( is(PropertyType!(C2.extraProp) == long));
9077                 static assert( is(typeof(C2.extraProp) == long));
9078 
9079                 alias overloads = __traits(getOverloads, C2, "extraProp");
9080                 static assert(overloads.length == 3);
9081 
9082                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function() @property)));
9083                 static assert( is(PropertyType!(overloads[0]) == long));
9084                 static assert( is(typeof(overloads[0]) == long));
9085 
9086                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string) @property)));
9087                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
9088                 static assert(!__traits(compiles, typeof(overloads[1])));
9089 
9090                 static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(void function(int) @property)));
9091                 static assert(!__traits(compiles, PropertyType!(overloads[2])));
9092                 static assert(!__traits(compiles, typeof(overloads[2])));
9093             }
9094 
9095             // override void foo()
9096             static assert( is(SymbolType!(C2.foo) == ToFunctionType!(void function())));
9097             static assert(!__traits(compiles, PropertyType!(C2.foo)));
9098             static assert( is(typeof(C2.foo) == SymbolType!(C2.foo)));
9099 
9100             // I does not provide default arguments, but C2 does.
9101             // @property string defaultArgInDerivedProp2(int i = 0);
9102             // @property void defaultArgInDerivedProp2(string, int i = 0);
9103             {
9104                 static assert( is(SymbolType!(C2.defaultArgInDerivedProp2) ==
9105                                   ToFunctionType!(string function(int) @property)));
9106                 static assert( is(PropertyType!(C2.defaultArgInDerivedProp2) == string));
9107                 static assert( is(typeof(C2.defaultArgInDerivedProp2) == string));
9108 
9109                 alias overloads = __traits(getOverloads, C2, "defaultArgInDerivedProp2");
9110                 static assert(overloads.length == 2);
9111 
9112                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int) @property)));
9113                 static assert( is(PropertyType!(overloads[0]) == string));
9114                 static assert( is(typeof(overloads[0]) == string));
9115 
9116                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int) @property)));
9117                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
9118                 static assert(!__traits(compiles, typeof(overloads[1])));
9119             }
9120 
9121             // I does not provide default arguments, but C2 does.
9122             // string defaultArgInDerived2(int i = 0);
9123             // void defaultArgInDerived2(string, int i = 0);
9124             {
9125                 static assert( is(SymbolType!(C2.defaultArgInDerived2) == ToFunctionType!(string function(int))));
9126                 static assert( is(PropertyType!(C2.defaultArgInDerived2) == string));
9127                 static assert( is(typeof(C2.defaultArgInDerived2) == SymbolType!(C2.defaultArgInDerived2)));
9128 
9129                 alias overloads = __traits(getOverloads, C2, "defaultArgInDerived2");
9130                 static assert(overloads.length == 2);
9131 
9132                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int))));
9133                 static assert( is(PropertyType!(overloads[0]) == string));
9134                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
9135 
9136                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int))));
9137                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
9138                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
9139             }
9140 
9141             // I does not provide default arguments, but C2 does.
9142             // void defaultArgInDerived1(string, int i = 0);
9143             // string defaultArgInDerived1(int i = 0);
9144             {
9145                 static assert( is(SymbolType!(C2.defaultArgInDerived1) == ToFunctionType!(void function(string, int))));
9146                 static assert( is(PropertyType!(C2.defaultArgInDerived1) == string));
9147                 static assert( is(typeof(C2.defaultArgInDerived1) == SymbolType!(C2.defaultArgInDerived1)));
9148 
9149                 alias overloads = __traits(getOverloads, C2, "defaultArgInDerived1");
9150                 static assert(overloads.length == 2);
9151 
9152                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int))));
9153                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9154                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
9155 
9156                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int))));
9157                 static assert( is(PropertyType!(overloads[1]) == string));
9158                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
9159             }
9160 
9161             // I does not provide default arguments, but C2 does.
9162             // @property void defaultArgInDerivedProp1(string, int i = 0);
9163             // @property string defaultArgInDerivedProp1(int i = 0);
9164             {
9165                 static assert( is(SymbolType!(C2.defaultArgInDerivedProp1) ==
9166                                   ToFunctionType!(void function(string, int) @property)));
9167                 static assert( is(PropertyType!(C2.defaultArgInDerivedProp1) == string));
9168                 static assert( is(typeof(C2.defaultArgInDerivedProp1) == string));
9169 
9170                 alias overloads = __traits(getOverloads, C2, "defaultArgInDerivedProp1");
9171                 static assert(overloads.length == 2);
9172 
9173                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int) @property)));
9174                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9175                 static assert(!__traits(compiles, typeof(overloads[0])));
9176 
9177                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int) @property)));
9178                 static assert( is(PropertyType!(overloads[1]) == string));
9179                 static assert( is(typeof(overloads[1]) == string));
9180             }
9181 
9182             // override void defaultArg2(int, string str = "bar");
9183             // override int defaultArg2(string str = "bar");
9184             {
9185                 static assert( is(SymbolType!(C2.defaultArg2) == ToFunctionType!(void function(int, string))));
9186                 static assert( is(PropertyType!(C2.defaultArg2) == int));
9187                 static assert( is(typeof(C2.defaultArg2) == SymbolType!(C2.defaultArg2)));
9188 
9189                 alias overloads = __traits(getOverloads, C2, "defaultArg2");
9190                 static assert(overloads.length == 2);
9191 
9192                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string))));
9193                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9194                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
9195 
9196                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string))));
9197                 static assert( is(PropertyType!(overloads[1]) == int));
9198                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
9199             }
9200 
9201             // override @property int defaultArgProp2(string str = "bar");
9202             // override @property void defaultArgProp2(int, string str = "bar");
9203             {
9204                 static assert( is(SymbolType!(C2.defaultArgProp2) ==
9205                                   ToFunctionType!(int function(string) @property)));
9206                 static assert( is(PropertyType!(C2.defaultArgProp2) == int));
9207                 static assert( is(typeof(C2.defaultArgProp2) == PropertyType!(C2.defaultArgProp2)));
9208 
9209                 alias overloads = __traits(getOverloads, C2, "defaultArgProp2");
9210                 static assert(overloads.length == 2);
9211 
9212                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string) @property)));
9213                 static assert( is(PropertyType!(overloads[0]) == int));
9214                 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
9215 
9216                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string) @property)));
9217                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
9218                 static assert(!__traits(compiles, typeof(overloads[1])));
9219             }
9220 
9221             // override @property void defaultArgProp1(int, string str = "bar");
9222             // override @property int defaultArgProp1(string str = "bar");
9223             {
9224 
9225                 static assert( is(SymbolType!(C2.defaultArgProp1) ==
9226                                   ToFunctionType!(void function(int, string) @property)));
9227                 static assert( is(PropertyType!(C2.defaultArgProp1) == int));
9228                 static assert( is(typeof(C2.defaultArgProp1) == PropertyType!(C2.defaultArgProp1)));
9229 
9230                 alias overloads = __traits(getOverloads, C2, "defaultArgProp1");
9231                 static assert(overloads.length == 2);
9232 
9233                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string) @property)));
9234                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9235                 static assert(!__traits(compiles, typeof(overloads[0])));
9236 
9237                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string) @property)));
9238                 static assert( is(PropertyType!(overloads[1]) == int));
9239                 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
9240             }
9241 
9242             // override void defaultArg1(int, string str = "bar");
9243             // override int defaultArg1(string str = "bar");
9244             {
9245                 static assert( is(SymbolType!(C2.defaultArg1) == ToFunctionType!(void function(int, string))));
9246                 static assert( is(PropertyType!(C2.defaultArg1) == int));
9247                 static assert( is(typeof(C2.defaultArg1) == SymbolType!(C2.defaultArg1)));
9248 
9249                 alias overloads = __traits(getOverloads, C2, "defaultArg1");
9250                 static assert(overloads.length == 2);
9251 
9252                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string))));
9253                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9254                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
9255 
9256                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string))));
9257                 static assert( is(PropertyType!(overloads[1]) == int));
9258                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
9259             }
9260 
9261             // override @property void prop2(int);
9262             // override @property int prop2();
9263             {
9264                 static assert( is(SymbolType!(C2.prop2) == ToFunctionType!(void function(int) @property)));
9265                 static assert( is(PropertyType!(C2.prop2) == int));
9266                 static assert( is(typeof(C2.prop2) == PropertyType!(C2.prop2)));
9267 
9268                 alias overloads = __traits(getOverloads, C2, "prop2");
9269                 static assert(overloads.length == 2);
9270 
9271                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property)));
9272                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9273                 static assert(!__traits(compiles, typeof(overloads[0])));
9274 
9275                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property)));
9276                 static assert( is(PropertyType!(overloads[1]) == int));
9277                 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
9278             }
9279 
9280             // override @property void prop1(int);
9281             // override @property int prop1();
9282             {
9283                 static assert( is(SymbolType!(C2.prop1) == ToFunctionType!(void function(int) @property)));
9284                 static assert( is(PropertyType!(C2.prop1) == int));
9285                 static assert( is(typeof(C2.prop1) == PropertyType!(C2.prop1)));
9286 
9287                 alias overloads = __traits(getOverloads, C2, "prop1");
9288                 static assert(overloads.length == 2);
9289 
9290                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property)));
9291                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9292                 static assert(!__traits(compiles, typeof(overloads[0])));
9293 
9294                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property)));
9295                 static assert( is(PropertyType!(overloads[1]) == int));
9296                 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
9297             }
9298 
9299             // override void func2(int);
9300             // override int func2();
9301             {
9302                 static assert( is(SymbolType!(C2.func2) == ToFunctionType!(void function(int))));
9303                 static assert( is(PropertyType!(C2.func2) == int));
9304                 static assert( is(typeof(C2.func2) == SymbolType!(C2.func2)));
9305 
9306                 alias overloads = __traits(getOverloads, C2, "func2");
9307                 static assert(overloads.length == 2);
9308 
9309                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int))));
9310                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9311                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
9312 
9313                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function())));
9314                 static assert( is(PropertyType!(overloads[1]) == int));
9315                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
9316             }
9317 
9318             // override int func1();
9319             // override void func1(int);
9320             {
9321                 static assert( is(SymbolType!(C2.func1) == ToFunctionType!(int function())));
9322                 static assert( is(PropertyType!(C2.func1) == int));
9323                 static assert( is(typeof(C2.func1) == SymbolType!(C2.func1)));
9324 
9325                 alias overloads = __traits(getOverloads, C2, "func1");
9326                 static assert(overloads.length == 2);
9327 
9328                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function())));
9329                 static assert( is(PropertyType!(overloads[0]) == int));
9330                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
9331 
9332                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int))));
9333                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
9334                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
9335             }
9336         }
9337 
9338         static class C3 : C2
9339         {
9340             const(short)* ptr;
9341         }
9342 
9343         {
9344             // real r; (from C2)
9345             // bool b; (from C2)
9346             // const(short)* ptr; (shadows C2.ptr)
9347             static assert( is(SymbolType!(C3.r) == real));
9348             static assert( is(PropertyType!(C3.r) == real));
9349             static assert( is(typeof(C3.r) == real));
9350 
9351             static assert( is(SymbolType!(C3.b) == bool));
9352             static assert( is(PropertyType!(C3.b) == bool));
9353             static assert( is(typeof(C3.b) == bool));
9354 
9355             static assert( is(SymbolType!(C3.ptr) == const(short)*));
9356             static assert( is(PropertyType!(C3.ptr) == const(short)*));
9357             static assert( is(typeof(C3.ptr) == const(short)*));
9358 
9359             // Actually on I, not C3.
9360             // static @property string staticProp();
9361             // static @property void staticProp(real);
9362             {
9363                 static assert( is(SymbolType!(C3.staticProp) == ToFunctionType!(string function() @property)));
9364                 static assert( is(PropertyType!(C3.staticProp) == string));
9365                 static assert( is(typeof(C3.staticProp) == PropertyType!(C3.staticProp)));
9366 
9367                 alias overloads = __traits(getOverloads, C3, "staticProp");
9368                 static assert(overloads.length == 2);
9369 
9370                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function() @property)));
9371                 static assert( is(PropertyType!(overloads[0]) == string));
9372                 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
9373 
9374                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(real) @property)));
9375                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
9376                 static assert(!__traits(compiles, typeof(overloads[1])));
9377             }
9378 
9379             // @property long extraProp() { return 42; }
9380             // override @property void extraProp(string) {}
9381             // @property void extraProp(int) {}
9382             {
9383                 static assert( is(SymbolType!(C3.extraProp) == ToFunctionType!(long function() @property)));
9384                 static assert( is(PropertyType!(C3.extraProp) == long));
9385                 static assert( is(typeof(C3.extraProp) == long));
9386 
9387                 alias overloads = __traits(getOverloads, C3, "extraProp");
9388                 static assert(overloads.length == 3);
9389 
9390                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function() @property)));
9391                 static assert( is(PropertyType!(overloads[0]) == long));
9392                 static assert( is(typeof(overloads[0]) == long));
9393 
9394                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string) @property)));
9395                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
9396                 static assert(!__traits(compiles, typeof(overloads[1])));
9397 
9398                 static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(void function(int) @property)));
9399                 static assert(!__traits(compiles, PropertyType!(overloads[2])));
9400                 static assert(!__traits(compiles, typeof(overloads[2])));
9401             }
9402 
9403             // override void foo()
9404             static assert( is(SymbolType!(C3.foo) == ToFunctionType!(void function())));
9405             static assert(!__traits(compiles, PropertyType!(C3.foo)));
9406             static assert( is(typeof(C3.foo) == SymbolType!(C3.foo)));
9407 
9408             // I does not provide default arguments, but C2 does.
9409             // @property string defaultArgInDerivedProp2(int i = 0);
9410             // @property void defaultArgInDerivedProp2(string, int i = 0);
9411             {
9412                 static assert( is(SymbolType!(C3.defaultArgInDerivedProp2) ==
9413                                   ToFunctionType!(string function(int) @property)));
9414                 static assert( is(PropertyType!(C3.defaultArgInDerivedProp2) == string));
9415                 static assert( is(typeof(C3.defaultArgInDerivedProp2) == string));
9416 
9417                 alias overloads = __traits(getOverloads, C3, "defaultArgInDerivedProp2");
9418                 static assert(overloads.length == 2);
9419 
9420                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int) @property)));
9421                 static assert( is(PropertyType!(overloads[0]) == string));
9422                 static assert( is(typeof(overloads[0]) == string));
9423 
9424                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int) @property)));
9425                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
9426                 static assert(!__traits(compiles, typeof(overloads[1])));
9427             }
9428 
9429             // I does not provide default arguments, but C2 does.
9430             // string defaultArgInDerived2(int i = 0);
9431             // void defaultArgInDerived2(string, int i = 0);
9432             {
9433                 static assert( is(SymbolType!(C3.defaultArgInDerived2) == ToFunctionType!(string function(int))));
9434                 static assert( is(PropertyType!(C3.defaultArgInDerived2) == string));
9435                 static assert( is(typeof(C3.defaultArgInDerived2) == SymbolType!(C3.defaultArgInDerived2)));
9436 
9437                 alias overloads = __traits(getOverloads, C3, "defaultArgInDerived2");
9438                 static assert(overloads.length == 2);
9439 
9440                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int))));
9441                 static assert( is(PropertyType!(overloads[0]) == string));
9442                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
9443 
9444                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int))));
9445                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
9446                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
9447             }
9448 
9449             // I does not provide default arguments, but C2 does.
9450             // void defaultArgInDerived1(string, int i = 0);
9451             // string defaultArgInDerived1(int i = 0);
9452             {
9453                 static assert( is(SymbolType!(C3.defaultArgInDerived1) == ToFunctionType!(void function(string, int))));
9454                 static assert( is(PropertyType!(C3.defaultArgInDerived1) == string));
9455                 static assert( is(typeof(C3.defaultArgInDerived1) == SymbolType!(C3.defaultArgInDerived1)));
9456 
9457                 alias overloads = __traits(getOverloads, C3, "defaultArgInDerived1");
9458                 static assert(overloads.length == 2);
9459 
9460                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int))));
9461                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9462                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
9463 
9464                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int))));
9465                 static assert( is(PropertyType!(overloads[1]) == string));
9466                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
9467             }
9468 
9469             // I does not provide default arguments, but C2 does.
9470             // @property void defaultArgInDerivedProp1(string, int i = 0);
9471             // @property string defaultArgInDerivedProp1(int i = 0);
9472             {
9473                 static assert( is(SymbolType!(C3.defaultArgInDerivedProp1) ==
9474                                   ToFunctionType!(void function(string, int) @property)));
9475                 static assert( is(PropertyType!(C3.defaultArgInDerivedProp1) == string));
9476                 static assert( is(typeof(C3.defaultArgInDerivedProp1) == string));
9477 
9478                 alias overloads = __traits(getOverloads, C3, "defaultArgInDerivedProp1");
9479                 static assert(overloads.length == 2);
9480 
9481                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int) @property)));
9482                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9483                 static assert(!__traits(compiles, typeof(overloads[0])));
9484 
9485                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int) @property)));
9486                 static assert( is(PropertyType!(overloads[1]) == string));
9487                 static assert( is(typeof(overloads[1]) == string));
9488             }
9489 
9490             // override void defaultArg2(int, string str = "bar");
9491             // override int defaultArg2(string str = "bar");
9492             {
9493                 static assert( is(SymbolType!(C3.defaultArg2) == ToFunctionType!(void function(int, string))));
9494                 static assert( is(PropertyType!(C3.defaultArg2) == int));
9495                 static assert( is(typeof(C3.defaultArg2) == SymbolType!(C3.defaultArg2)));
9496 
9497                 alias overloads = __traits(getOverloads, C3, "defaultArg2");
9498                 static assert(overloads.length == 2);
9499 
9500                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string))));
9501                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9502                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
9503 
9504                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string))));
9505                 static assert( is(PropertyType!(overloads[1]) == int));
9506                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
9507             }
9508 
9509             // override @property int defaultArgProp2(string str = "bar");
9510             // override @property void defaultArgProp2(int, string str = "bar");
9511             {
9512                 static assert( is(SymbolType!(C3.defaultArgProp2) ==
9513                                   ToFunctionType!(int function(string) @property)));
9514                 static assert( is(PropertyType!(C3.defaultArgProp2) == int));
9515                 static assert( is(typeof(C3.defaultArgProp2) == PropertyType!(C3.defaultArgProp2)));
9516 
9517                 alias overloads = __traits(getOverloads, C3, "defaultArgProp2");
9518                 static assert(overloads.length == 2);
9519 
9520                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string) @property)));
9521                 static assert( is(PropertyType!(overloads[0]) == int));
9522                 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0])));
9523 
9524                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string) @property)));
9525                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
9526                 static assert(!__traits(compiles, typeof(overloads[1])));
9527             }
9528 
9529             // override @property void defaultArgProp1(int, string str = "bar");
9530             // override @property int defaultArgProp1(string str = "bar");
9531             {
9532 
9533                 static assert( is(SymbolType!(C3.defaultArgProp1) ==
9534                                   ToFunctionType!(void function(int, string) @property)));
9535                 static assert( is(PropertyType!(C3.defaultArgProp1) == int));
9536                 static assert( is(typeof(C3.defaultArgProp1) == PropertyType!(C3.defaultArgProp1)));
9537 
9538                 alias overloads = __traits(getOverloads, C3, "defaultArgProp1");
9539                 static assert(overloads.length == 2);
9540 
9541                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string) @property)));
9542                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9543                 static assert(!__traits(compiles, typeof(overloads[0])));
9544 
9545                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string) @property)));
9546                 static assert( is(PropertyType!(overloads[1]) == int));
9547                 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
9548             }
9549 
9550             // override void defaultArg1(int, string str = "bar");
9551             // override int defaultArg1(string str = "bar");
9552             {
9553                 static assert( is(SymbolType!(C3.defaultArg1) == ToFunctionType!(void function(int, string))));
9554                 static assert( is(PropertyType!(C3.defaultArg1) == int));
9555                 static assert( is(typeof(C3.defaultArg1) == SymbolType!(C3.defaultArg1)));
9556 
9557                 alias overloads = __traits(getOverloads, C3, "defaultArg1");
9558                 static assert(overloads.length == 2);
9559 
9560                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string))));
9561                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9562                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
9563 
9564                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string))));
9565                 static assert( is(PropertyType!(overloads[1]) == int));
9566                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
9567             }
9568 
9569             // override @property void prop2(int);
9570             // override @property int prop2();
9571             {
9572                 static assert( is(SymbolType!(C3.prop2) == ToFunctionType!(void function(int) @property)));
9573                 static assert( is(PropertyType!(C3.prop2) == int));
9574                 static assert( is(typeof(C3.prop2) == PropertyType!(C3.prop2)));
9575 
9576                 alias overloads = __traits(getOverloads, C3, "prop2");
9577                 static assert(overloads.length == 2);
9578 
9579                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property)));
9580                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9581                 static assert(!__traits(compiles, typeof(overloads[0])));
9582 
9583                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property)));
9584                 static assert( is(PropertyType!(overloads[1]) == int));
9585                 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
9586             }
9587 
9588             // override @property void prop1(int);
9589             // override @property int prop1();
9590             {
9591                 static assert( is(SymbolType!(C3.prop1) == ToFunctionType!(void function(int) @property)));
9592                 static assert( is(PropertyType!(C3.prop1) == int));
9593                 static assert( is(typeof(C3.prop1) == PropertyType!(C3.prop1)));
9594 
9595                 alias overloads = __traits(getOverloads, C3, "prop1");
9596                 static assert(overloads.length == 2);
9597 
9598                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property)));
9599                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9600                 static assert(!__traits(compiles, typeof(overloads[0])));
9601 
9602                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property)));
9603                 static assert( is(PropertyType!(overloads[1]) == int));
9604                 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1])));
9605             }
9606 
9607             // override void func2(int);
9608             // override int func2();
9609             {
9610                 static assert( is(SymbolType!(C3.func2) == ToFunctionType!(void function(int))));
9611                 static assert( is(PropertyType!(C3.func2) == int));
9612                 static assert( is(typeof(C3.func2) == SymbolType!(C3.func2)));
9613 
9614                 alias overloads = __traits(getOverloads, C3, "func2");
9615                 static assert(overloads.length == 2);
9616 
9617                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int))));
9618                 static assert(!__traits(compiles, PropertyType!(overloads[0])));
9619                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
9620 
9621                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function())));
9622                 static assert( is(PropertyType!(overloads[1]) == int));
9623                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
9624             }
9625 
9626             // override int func1();
9627             // override void func1(int);
9628             {
9629                 static assert( is(SymbolType!(C3.func1) == ToFunctionType!(int function())));
9630                 static assert( is(PropertyType!(C3.func1) == int));
9631                 static assert( is(typeof(C3.func1) == SymbolType!(C3.func1)));
9632 
9633                 alias overloads = __traits(getOverloads, C3, "func1");
9634                 static assert(overloads.length == 2);
9635 
9636                 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function())));
9637                 static assert( is(PropertyType!(overloads[0]) == int));
9638                 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0])));
9639 
9640                 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int))));
9641                 static assert(!__traits(compiles, PropertyType!(overloads[1])));
9642                 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1])));
9643             }
9644         }
9645     }
9646 }
9647 
9648 // This is probably overkill, since it's arguably testing the compiler more
9649 // than it's testing SymbolType or ToFunctionType, but with various tests
9650 // either using inference for all attributes or not providing a body to avoid
9651 // it entirely, it seemed prudent to add some tests where the attributes being
9652 // inferred were better controlled, and it does help ensure that SymbolType
9653 // and ToFunctionType behave as expected in each case.
9654 @safe unittest
9655 {
9656     static int var;
9657 
9658     // Since these are actually called below (even if those functions aren't
9659     // called) we can't play the trick of not providing a body to set all of
9660     // the attributes, because we get linker errors when the functions below
9661     // call these functions.
9662     static void useGC() @safe pure nothrow { new int; }
9663     static void throws() @safe pure @nogc { Exception e; throw e; }
9664     static void impure() @safe nothrow @nogc { ++var; }
9665     static void unsafe() @system pure nothrow @nogc { int i; int* ptr = &i; }
9666 
9667     {
9668         static void func() { useGC(); }
9669         static assert( is(typeof(func) == ToFunctionType!(void function() @safe pure nothrow)));
9670         static assert( is(SymbolType!func == ToFunctionType!(void function() @safe pure nothrow)));
9671     }
9672     {
9673         static void func() { throws(); }
9674         static assert( is(typeof(func) == ToFunctionType!(void function() @safe pure @nogc)));
9675         static assert( is(SymbolType!func == ToFunctionType!(void function() @safe pure @nogc)));
9676     }
9677     {
9678         static void func() { impure(); }
9679         static assert( is(typeof(func) == ToFunctionType!(void function() @safe nothrow @nogc)));
9680         static assert( is(SymbolType!func == ToFunctionType!(void function() @safe nothrow @nogc)));
9681     }
9682     {
9683         static void func() { unsafe(); }
9684         static assert( is(typeof(func) == ToFunctionType!(void function() @system pure nothrow @nogc)));
9685 
9686         // Doubling the test shouldn't be necessary, but since the order of the
9687         // attributes isn't supposed to matter, it seemed prudent to have at
9688         // least one test that used a different order.
9689         static assert( is(SymbolType!func == ToFunctionType!(void function() @system pure nothrow @nogc)));
9690         static assert( is(SymbolType!func == ToFunctionType!(void function() @nogc nothrow pure @system)));
9691     }
9692     {
9693         static void func() { useGC(); throws(); }
9694         static assert( is(typeof(func) == ToFunctionType!(void function() @safe pure)));
9695         static assert( is(SymbolType!func == ToFunctionType!(void function() @safe pure)));
9696     }
9697     {
9698         static void func() { throws(); impure(); }
9699         static assert( is(typeof(func) == ToFunctionType!(void function() @safe @nogc)));
9700         static assert( is(SymbolType!func == ToFunctionType!(void function() @safe @nogc)));
9701     }
9702     {
9703         static void func() { impure(); unsafe(); }
9704         static assert( is(typeof(func) == ToFunctionType!(void function() @system nothrow @nogc)));
9705         static assert( is(SymbolType!func == ToFunctionType!(void function() @system nothrow @nogc)));
9706     }
9707     {
9708         static void func() { useGC(); unsafe(); }
9709         static assert( is(typeof(func) == ToFunctionType!(void function() @system pure nothrow)));
9710         static assert( is(SymbolType!func == ToFunctionType!(void function() @system pure nothrow)));
9711     }
9712     {
9713         static void func() { useGC(); throws(); impure(); unsafe(); }
9714         static assert( is(typeof(func) == ToFunctionType!(void function() @system)));
9715         static assert( is(SymbolType!func == ToFunctionType!(void function() @system)));
9716     }
9717     {
9718         static void func() @trusted { useGC(); throws(); impure(); unsafe(); }
9719         static assert( is(typeof(func) == ToFunctionType!(void function() @trusted)));
9720         static assert( is(SymbolType!func == ToFunctionType!(void function() @trusted)));
9721     }
9722 }
9723 
9724 /++
9725     Removes the outer layer of $(D const), $(D inout), or $(D immutable)
9726     from type $(D T).
9727 
9728     If none of those qualifiers have been applied to the outer layer of
9729     type $(D T), then the result is $(D T).
9730 
9731     For the built-in scalar types (that is $(D bool), the character types, and
9732     the numeric types), they only have one layer, so $(D const U) simply becomes
9733     $(D U).
9734 
9735     Where the layers come in is pointers and arrays. $(D const(U*)) becomes
9736     $(D const(U)*), and $(D const(U[])), becomes $(D const(U)[]). So, a pointer
9737     goes from being fully $(D const) to being a mutable pointer to $(D const),
9738     and a dynamic array goes from being fully $(D const) to being a mutable
9739     dynamic array of $(D const) elements. And if there are multiple layers of
9740     pointers or arrays, it's just that outer layer which is affected - e.g.
9741     $(D const(U**)) would become $(D const(U*)*).
9742 
9743     For user-defined types, the effect is that $(D const U) becomes $(D U), and
9744     how that affects member variables depends on the type of the member
9745     variable. If a member variable is explicitly marked with any mutability
9746     qualifiers, then it will continue to have those qualifiers even after
9747     Unconst has stripped all mutability qualifiers from the containing type.
9748     However, if a mutability qualifier was on the member variable only because
9749     the containing type had that qualifier, then when Unconst removes the
9750     qualifier from the containing type, it is removed from the member variable
9751     as well.
9752 
9753     Also, Unconst has no effect on what a templated type is instantiated
9754     with, so if a templated type is instantiated with a template argument which
9755     has a mutability qualifier, the template instantiation will not change.
9756   +/
9757 version (StdDdoc) template Unconst(T)
9758 {
9759     import core.internal.traits : CoreUnconst = Unconst;
9760     alias Unconst = CoreUnconst!T;
9761 }
9762 else
9763 {
9764     import core.internal.traits : CoreUnconst = Unconst;
9765     alias Unconst = CoreUnconst;
9766 }
9767 
9768 ///
9769 @safe unittest
9770 {
9771     static assert(is(Unconst!(                   int) == int));
9772     static assert(is(Unconst!(             const int) == int));
9773     static assert(is(Unconst!(       inout       int) == int));
9774     static assert(is(Unconst!(       inout const int) == int));
9775     static assert(is(Unconst!(shared             int) == shared int));
9776     static assert(is(Unconst!(shared       const int) == shared int));
9777     static assert(is(Unconst!(shared inout       int) == shared int));
9778     static assert(is(Unconst!(shared inout const int) == shared int));
9779     static assert(is(Unconst!(         immutable int) == int));
9780 
9781     // Only the outer layer of immutable is removed.
9782     // immutable(int[]) -> immutable(int)[]
9783     alias ImmIntArr = immutable(int[]);
9784     static assert(is(Unconst!ImmIntArr == immutable(int)[]));
9785 
9786     // Only the outer layer of const is removed.
9787     // immutable(int*) -> immutable(int)*
9788     alias ConstIntPtr = const(int*);
9789     static assert(is(Unconst!ConstIntPtr == const(int)*));
9790 
9791     // const(int)* -> const(int)*
9792     alias PtrToConstInt = const(int)*;
9793     static assert(is(Unconst!PtrToConstInt == const(int)*));
9794 
9795     static struct S
9796     {
9797         int* ptr;
9798         const int* cPtr;
9799         shared int* sPtr;
9800     }
9801 
9802     const S s;
9803     static assert(is(typeof(s) == const S));
9804     static assert(is(typeof(typeof(s).ptr) == const int*));
9805     static assert(is(typeof(typeof(s).cPtr) == const int*));
9806     static assert(is(typeof(typeof(s).sPtr) == const shared int*));
9807 
9808     // For user-defined types, all mutability qualifiers that are applied to
9809     // member variables only because the containing type has them are removed,
9810     // but the ones that are directly on those member variables remain.
9811 
9812     // const S -> S
9813     static assert(is(Unconst!(typeof(s)) == S));
9814     static assert(is(typeof(Unconst!(typeof(s)).ptr) == int*));
9815     static assert(is(typeof(Unconst!(typeof(s)).cPtr) == const int*));
9816     static assert(is(typeof(Unconst!(typeof(s)).sPtr) == shared int*));
9817 
9818     static struct Foo(T)
9819     {
9820         T* ptr;
9821     }
9822 
9823     // The qualifier on the type is removed, but the qualifier on the template
9824     // argument is not.
9825     static assert(is(Unconst!(const(Foo!(const int))) == Foo!(const int)));
9826     static assert(is(Unconst!(Foo!(const int)) == Foo!(const int)));
9827     static assert(is(Unconst!(const(Foo!int)) == Foo!int));
9828 }
9829 
9830 /++
9831     Removes the outer layer of $(D shared) from type $(D T).
9832 
9833     If $(D shared) has not been applied to the outer layer of type $(D T), then
9834     the result is $(D T).
9835 
9836     Note that while $(D immutable) is implicitly $(D shared), it is unaffected
9837     by Unshared. Only explicit $(D shared) is removed.
9838 
9839     For the built-in scalar types (that is $(D bool), the character types, and
9840     the numeric types), they only have one layer, so $(D shared U) simply
9841     becomes $(D U).
9842 
9843     Where the layers come in is pointers and arrays. $(D shared(U*)) becomes
9844     $(D shared(U)*), and $(D shared(U[])), becomes $(D shared(U)[]). So, a
9845     pointer goes from being fully $(D shared) to being a mutable pointer to
9846     $(D shared), and a dynamic array goes from being fully $(D shared) to being
9847     a mutable dynamic array of $(D shared) elements. And if there are multiple
9848     layers of pointers or arrays, it's just that outer layer which is affected
9849     - e.g. $(D shared(U**)) would become $(D shared(U*)*).
9850 
9851     For user-defined types, the effect is that $(D shared U) becomes $(D U),
9852     and how that affects member variables depends on the type of the member
9853     variable. If a member variable is explicitly marked with $(D shared), then
9854     it will continue to be $(D shared) even after Unshared has stripped
9855     $(D shared) from the containing type. However, if $(D shared) was on the
9856     member variable only because the containing type was $(D shared), then when
9857     Unshared removes the qualifier from the containing type, it is removed from
9858     the member variable as well.
9859 
9860     Also, Unshared has no effect on what a templated type is instantiated
9861     with, so if a templated type is instantiated with a template argument which
9862     has a type qualifier, the template instantiation will not change.
9863   +/
9864 template Unshared(T)
9865 {
9866     static if (is(T == shared U, U))
9867         alias Unshared = U;
9868     else
9869         alias Unshared = T;
9870 }
9871 
9872 ///
9873 @safe unittest
9874 {
9875     static assert(is(Unshared!(                   int) == int));
9876     static assert(is(Unshared!(             const int) == const int));
9877     static assert(is(Unshared!(       inout       int) == inout int));
9878     static assert(is(Unshared!(       inout const int) == inout const int));
9879     static assert(is(Unshared!(shared             int) == int));
9880     static assert(is(Unshared!(shared       const int) == const int));
9881     static assert(is(Unshared!(shared inout       int) == inout int));
9882     static assert(is(Unshared!(shared inout const int) == inout const int));
9883     static assert(is(Unshared!(         immutable int) == immutable int));
9884 
9885     // Only the outer layer of shared is removed.
9886     // shared(int[]) -> shared(int)[]
9887     alias SharedIntArr = shared(int[]);
9888     static assert(is(Unshared!SharedIntArr == shared(int)[]));
9889 
9890     // Only the outer layer of shared is removed.
9891     // shared(int*) -> shared(int)*
9892     alias SharedIntPtr = shared(int*);
9893     static assert(is(Unshared!SharedIntPtr == shared(int)*));
9894 
9895     // shared(int)* -> shared(int)*
9896     alias PtrToSharedInt = shared(int)*;
9897     static assert(is(Unshared!PtrToSharedInt == shared(int)*));
9898 
9899     // immutable is unaffected
9900     alias ImmutableArr = immutable(int[]);
9901     static assert(is(Unshared!ImmutableArr == immutable(int[])));
9902 
9903     static struct S
9904     {
9905         int* ptr;
9906         const int* cPtr;
9907         shared int* sPtr;
9908     }
9909 
9910     shared S s;
9911     static assert(is(typeof(s) == shared S));
9912     static assert(is(typeof(typeof(s).ptr) == shared int*));
9913     static assert(is(typeof(typeof(s).cPtr) == const shared int*));
9914     static assert(is(typeof(typeof(s).sPtr) == shared int*));
9915 
9916     // For user-defined types, if shared is applied to a member variable only
9917     // because the containing type is shared, then shared is removed from that
9918     // member variable, but if the member variable is directly marked as shared,
9919     // then it continues to be shared.
9920 
9921     // shared S -> S
9922     static assert(is(Unshared!(typeof(s)) == S));
9923     static assert(is(typeof(Unshared!(typeof(s)).ptr) == int*));
9924     static assert(is(typeof(Unshared!(typeof(s)).cPtr) == const int*));
9925     static assert(is(typeof(Unshared!(typeof(s)).sPtr) == shared int*));
9926 
9927     static struct Foo(T)
9928     {
9929         T* ptr;
9930     }
9931 
9932     // The qualifier on the type is removed, but the qualifier on the template
9933     // argument is not.
9934     static assert(is(Unshared!(shared(Foo!(shared int))) == Foo!(shared int)));
9935     static assert(is(Unshared!(Foo!(shared int)) == Foo!(shared int)));
9936     static assert(is(Unshared!(shared(Foo!int)) == Foo!int));
9937 }
9938 
9939 /++
9940     Removes the outer layer of all type qualifiers from type $(D T) - this
9941     includes $(D shared).
9942 
9943     If no type qualifiers have been applied to the outer layer of type $(D T),
9944     then the result is $(D T).
9945 
9946     For the built-in scalar types (that is $(D bool), the character types, and
9947     the numeric types), they only have one layer, so $(D const U) simply becomes
9948     $(D U).
9949 
9950     Where the layers come in is pointers and arrays. $(D const(U*)) becomes
9951     $(D const(U)*), and $(D const(U[])), becomes $(D const(U)[]). So, a pointer
9952     goes from being fully $(D const) to being a mutable pointer to $(D const),
9953     and a dynamic array goes from being fully $(D const) to being a mutable
9954     dynamic array of $(D const) elements. And if there are multiple layers of
9955     pointers or arrays, it's just that outer layer which is affected - e.g.
9956     $(D shared(U**)) would become $(D shared(U*)*).
9957 
9958     For user-defined types, the effect is that $(D const U) becomes $(D U), and
9959     how that affects member variables depends on the type of the member
9960     variable. If a member variable is explicitly marked with any qualifiers,
9961     then it will continue to have those qualifiers even after Unqualified has
9962     stripped all qualifiers from the containing type. However, if a qualifier
9963     was on the member variable only because the containing type had that
9964     qualifier, then when Unqualified removes the qualifier from the containing
9965     type, it is removed from the member variable as well.
9966 
9967     Also, Unqualified has no effect on what a templated type is instantiated
9968     with, so if a templated type is instantiated with a template argument which
9969     has a type qualifier, the template instantiation will not change.
9970 
9971     Note that in most cases, $(LREF Unconst) or $(LREF Unshared) should be used
9972     rather than Unqualified, because in most cases, code is not designed to
9973     work with $(D shared) and thus doing type checks which remove $(D shared)
9974     will allow $(D shared) types to pass template constraints when they won't
9975     actually work with the code. And when code is designed to work with
9976     $(D shared), it's often the case that the type checks need to take
9977     $(D const) into account in order to avoid accidentally mutating $(D const)
9978     data and violating the type system.
9979 
9980     In particular, historically, a lot of D code has used
9981     $(REF Unqual, std, traits) (which is equivalent to phobos.sys.traits'
9982     Unqualified) when the programmer's intent was to remove $(D const), and
9983     $(D shared) wasn't actually considered at all. And in such cases, the code
9984     really should use $(LREF Unconst) instead.
9985 
9986     But of course, if a template constraint or $(D static if) really needs to
9987     strip off both the mutability qualifiers and $(D shared) for what it's
9988     testing for, then that's what Unqualified is for. It's just that it's best
9989     practice to use $(LREF Unconst) when it's not clear that $(D shared) should
9990     be removed as well.
9991 
9992     Also, note that $(D is(immutable T == immutable U))) is equivalent to
9993     $(D is(Unqualified!T == Unqualified!U)) (using $(D immutable) converts
9994     $(D const), $(D inout), and $(D shared) to $(D immutable), whereas using
9995     Unqualified strips off all type qualifiers, but the resulting comparison is
9996     the same as long as $(D immutable) is used on both sides or Unqualified is
9997     used on both sides)). So, in cases where code needs to compare two types to
9998     see whether they're the same while ignoring all qualifiers, it's generally
9999     better to use $(D immutable) on both types rather than using Unqualfied on
10000     both types, since that avoids needing to instantiate a template, and those
10001     instantiations can really add up when a project has a lot of templates
10002     with template constraints, $(D static if)s, and other forms of conditional
10003     compilation that need to compare types.
10004   +/
10005 template Unqualified(T)
10006 {
10007     import core.internal.traits : CoreUnqualified = Unqual;
10008     alias Unqualified = CoreUnqualified!(T);
10009 }
10010 
10011 ///
10012 @safe unittest
10013 {
10014     static assert(is(Unqualified!(                   int) == int));
10015     static assert(is(Unqualified!(             const int) == int));
10016     static assert(is(Unqualified!(       inout       int) == int));
10017     static assert(is(Unqualified!(       inout const int) == int));
10018     static assert(is(Unqualified!(shared             int) == int));
10019     static assert(is(Unqualified!(shared       const int) == int));
10020     static assert(is(Unqualified!(shared inout       int) == int));
10021     static assert(is(Unqualified!(shared inout const int) == int));
10022     static assert(is(Unqualified!(         immutable int) == int));
10023 
10024     // Only the outer layer of immutable is removed.
10025     // immutable(int[]) -> immutable(int)[]
10026     alias ImmIntArr = immutable(int[]);
10027     static assert(is(Unqualified!ImmIntArr == immutable(int)[]));
10028 
10029     // Only the outer layer of const is removed.
10030     // const(int*) -> const(int)*
10031     alias ConstIntPtr = const(int*);
10032     static assert(is(Unqualified!ConstIntPtr == const(int)*));
10033 
10034     // const(int)* -> const(int)*
10035     alias PtrToConstInt = const(int)*;
10036     static assert(is(Unqualified!PtrToConstInt == const(int)*));
10037 
10038     // Only the outer layer of shared is removed.
10039     // shared(int*) -> shared(int)*
10040     alias SharedIntPtr = shared(int*);
10041     static assert(is(Unqualified!SharedIntPtr == shared(int)*));
10042 
10043     // shared(int)* -> shared(int)*
10044     alias PtrToSharedInt = shared(int)*;
10045     static assert(is(Unqualified!PtrToSharedInt == shared(int)*));
10046 
10047     // Both const and shared are removed from the outer layer.
10048     // shared const int[] -> shared(const(int))[]
10049     alias SharedConstIntArr = shared const(int[]);
10050     static assert(is(Unqualified!SharedConstIntArr == shared(const(int))[]));
10051 
10052     static struct S
10053     {
10054         int* ptr;
10055         const int* cPtr;
10056         shared int* sPtr;
10057     }
10058 
10059     shared const S s;
10060     static assert(is(typeof(s) == shared const S));
10061     static assert(is(typeof(typeof(s).ptr) == shared const int*));
10062     static assert(is(typeof(typeof(s).cPtr) == shared const int*));
10063     static assert(is(typeof(typeof(s).sPtr) == shared const int*));
10064 
10065     // For user-defined types, all qualifiers that are applied to member
10066     // variables only because the containing type has them are removed, but the
10067     // ones that are directly on those member variables remain.
10068 
10069     // shared const S -> S
10070     static assert(is(Unqualified!(typeof(s)) == S));
10071     static assert(is(typeof(Unqualified!(typeof(s)).ptr) == int*));
10072     static assert(is(typeof(Unqualified!(typeof(s)).cPtr) == const int*));
10073     static assert(is(typeof(Unqualified!(typeof(s)).sPtr) == shared int*));
10074 
10075     static struct Foo(T)
10076     {
10077         T* ptr;
10078     }
10079 
10080     // The qualifiers on the type are removed, but the qualifiers on the
10081     // template argument are not.
10082     static assert(is(Unqualified!(const(Foo!(const int))) == Foo!(const int)));
10083     static assert(is(Unqualified!(Foo!(const int)) == Foo!(const int)));
10084     static assert(is(Unqualified!(const(Foo!int)) == Foo!int));
10085 }
10086 
10087 /++
10088     Applies $(D const) to the given type.
10089 
10090     This is primarily useful in conjunction with templates that take a template
10091     predicate (such as many of the templates in phobos.sys.meta), since while in
10092     most cases, you can simply do $(D const T) or $(D const(T)) to make $(D T)
10093     $(D const), with something like $(REF Map, phobos, sys, meta), you need to
10094     pass a template to be applied.
10095 
10096     See_Also:
10097         $(LREF ImmutableOf)
10098         $(LREF InoutOf)
10099         $(LREF SharedOf)
10100   +/
10101 alias ConstOf(T) = const T;
10102 
10103 ///
10104 @safe unittest
10105 {
10106     static assert(is(ConstOf!int == const int));
10107     static assert(is(ConstOf!(const int) == const int));
10108     static assert(is(ConstOf!(inout int) == inout const int));
10109     static assert(is(ConstOf!(shared int) == const shared int));
10110 
10111     // Note that const has no effect on immutable.
10112     static assert(is(ConstOf!(immutable int) == immutable int));
10113 
10114     import phobos.sys.meta : AliasSeq, Map;
10115 
10116     alias Types = AliasSeq!(int, long,
10117                             bool*, ubyte[],
10118                             string, immutable(string));
10119     alias WithConst = Map!(ConstOf, Types);
10120     static assert(is(WithConst ==
10121                      AliasSeq!(const int, const long,
10122                                const(bool*), const(ubyte[]),
10123                                const(string), immutable(string))));
10124 }
10125 
10126 /++
10127     Applies $(D immutable) to the given type.
10128 
10129     This is primarily useful in conjunction with templates that take a template
10130     predicate (such as many of the templates in phobos.sys.meta), since while in
10131     most cases, you can simply do $(D immutable T) or $(D immutable(T)) to make
10132     $(D T) $(D immutable), with something like $(REF Map, phobos, sys, meta),
10133     you need to pass a template to be applied.
10134 
10135     See_Also:
10136         $(LREF ConstOf)
10137         $(LREF InoutOf)
10138         $(LREF SharedOf)
10139   +/
10140 alias ImmutableOf(T) = immutable T;
10141 
10142 ///
10143 @safe unittest
10144 {
10145     static assert(is(ImmutableOf!int == immutable int));
10146 
10147     // Note that immutable overrides const and inout.
10148     static assert(is(ImmutableOf!(const int) == immutable int));
10149     static assert(is(ImmutableOf!(inout int) == immutable int));
10150 
10151     // Note that immutable overrides shared, since immutable is implicitly
10152     // shared.
10153     static assert(is(ImmutableOf!(shared int) == immutable int));
10154 
10155     static assert(is(ImmutableOf!(immutable int) == immutable int));
10156 
10157     import phobos.sys.meta : AliasSeq, Map;
10158 
10159     alias Types = AliasSeq!(int, long,
10160                             bool*, ubyte[],
10161                             string, immutable(string));
10162     alias WithImmutable = Map!(ImmutableOf, Types);
10163     static assert(is(WithImmutable ==
10164                      AliasSeq!(immutable int, immutable long,
10165                                immutable(bool*), immutable(ubyte[]),
10166                                immutable(string), immutable(string))));
10167 }
10168 
10169 /++
10170     Applies $(D inout) to the given type.
10171 
10172     This is primarily useful in conjunction with templates that take a template
10173     predicate (such as many of the templates in phobos.sys.meta), since while in
10174     most cases, you can simply do $(D inout T) or $(D inout(T)) to make $(D T)
10175     $(D inout), with something like $(REF Map, phobos, sys, meta), you need to
10176     pass a template to be applied.
10177 
10178     See_Also:
10179         $(LREF ConstOf)
10180         $(LREF ImmutableOf)
10181         $(LREF SharedOf)
10182   +/
10183 alias InoutOf(T) = inout T;
10184 
10185 ///
10186 @safe unittest
10187 {
10188     static assert(is(InoutOf!int == inout int));
10189     static assert(is(InoutOf!(const int) == inout const int));
10190     static assert(is(InoutOf!(inout int) == inout int));
10191     static assert(is(InoutOf!(shared int) == inout shared int));
10192 
10193     // Note that inout has no effect on immutable.
10194     static assert(is(InoutOf!(immutable int) == immutable int));
10195 
10196     import phobos.sys.meta : AliasSeq, Map;
10197 
10198     alias Types = AliasSeq!(int, long,
10199                             bool*, ubyte[],
10200                             string, immutable(string));
10201     alias WithInout = Map!(InoutOf, Types);
10202     static assert(is(WithInout ==
10203                      AliasSeq!(inout int, inout long,
10204                                inout(bool*), inout(ubyte[]),
10205                                inout(string), immutable(string))));
10206 }
10207 
10208 /++
10209     Applies $(D shared) to the given type.
10210 
10211     This is primarily useful in conjunction with templates that take a template
10212     predicate (such as many of the templates in phobos.sys.meta), since while in
10213     most cases, you can simply do $(D shared T) or $(D shared(T)) to make $(D T)
10214     $(D shared), with something like $(REF Map, phobos, sys, meta), you need to
10215     pass a template to be applied.
10216 
10217     See_Also:
10218         $(LREF ConstOf)
10219         $(LREF ImmutableOf)
10220         $(LREF InoutOf)
10221   +/
10222 alias SharedOf(T) = shared T;
10223 
10224 ///
10225 @safe unittest
10226 {
10227     static assert(is(SharedOf!int == shared int));
10228     static assert(is(SharedOf!(const int) == const shared int));
10229     static assert(is(SharedOf!(inout int) == inout shared int));
10230     static assert(is(SharedOf!(shared int) == shared int));
10231 
10232     // Note that shared has no effect on immutable, since immutable is
10233     // implicitly shared.
10234     static assert(is(SharedOf!(immutable int) == immutable int));
10235 
10236     import phobos.sys.meta : AliasSeq, Map;
10237 
10238     alias Types = AliasSeq!(int, long,
10239                             bool*, ubyte[],
10240                             string, immutable(string));
10241     alias WithShared = Map!(SharedOf, Types);
10242     static assert(is(WithShared ==
10243                      AliasSeq!(shared int, shared long,
10244                                shared(bool*), shared(ubyte[]),
10245                                shared(string), immutable(string))));
10246 }
10247 
10248 // Needed for rvalueOf/lvalueOf because
10249 // "inout on return means inout must be on a parameter as well"
10250 private struct __InoutWorkaroundStruct {}
10251 
10252 /++
10253     Creates an lvalue or rvalue of type T to be used in conjunction with
10254     $(D is(typeof(...))) or
10255     $(DDSUBLINK spec/traits, compiles, $(D __traits(compiles, ...))).
10256 
10257     The idea is that some traits or other forms of conditional compilation need
10258     to verify that a particular piece of code compiles with an rvalue or an
10259     lvalue of a specific type, and these $(D @property) functions allow you to
10260     get an rvalue or lvalue of a specific type to use within an expression that
10261     is then tested to see whether it compiles.
10262 
10263     They're $(D @property) functions so that using $(D typeof) on them gives
10264     the return type rather than the type of the function.
10265 
10266     Note that these functions are $(I not) defined, so if they're actually used
10267     outside of type introspection, they'll result in linker errors. They're
10268     entirely for testing that a particular piece of code compiles with an rvalue
10269     or lvalue of the given type.
10270 
10271     The $(D __InoutWorkaroundStruct) parameter is entirely to make it so that
10272     these work when the given type has the $(D inout) qualifier, since the
10273     language requires that a function that returns an $(D inout) type also have
10274     an $(D inout) type as a parameter. It should just be ignored.
10275   +/
10276 @property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
10277 
10278 /++ Ditto +/
10279 @property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
10280 
10281 ///
10282 @safe unittest
10283 {
10284     static int foo(int);
10285     static assert(is(typeof(foo(lvalueOf!int)) == int));
10286     static assert(is(typeof(foo(rvalueOf!int)) == int));
10287 
10288     static bool bar(ref int);
10289     static assert(is(typeof(bar(lvalueOf!int)) == bool));
10290     static assert(!is(typeof(bar(rvalueOf!int))));
10291 
10292     static assert( is(typeof({ lvalueOf!int = 42; })));
10293     static assert(!is(typeof({ rvalueOf!int = 42; })));
10294 
10295     static struct S {}
10296     static assert( is(typeof({ lvalueOf!S = S.init; })));
10297     static assert(!is(typeof({ rvalueOf!S = S.init; })));
10298 
10299     static struct NoAssign
10300     {
10301         @disable void opAssign(ref NoAssign);
10302     }
10303     static assert(!is(typeof({ lvalueOf!NoAssign = NoAssign.init; })));
10304     static assert(!is(typeof({ rvalueOf!NoAssign = NoAssign.init; })));
10305 }
10306 
10307 @system unittest
10308 {
10309     import phobos.sys.meta : AliasSeq;
10310 
10311     void needLvalue(T)(ref T);
10312     static struct S {}
10313     int i;
10314     struct Nested { void f() { ++i; } }
10315 
10316     static foreach (T; AliasSeq!(int, const int, immutable int, inout int, string, S, Nested, Object))
10317     {
10318         static assert(!__traits(compiles, needLvalue(rvalueOf!T)));
10319         static assert( __traits(compiles, needLvalue(lvalueOf!T)));
10320         static assert(is(typeof(rvalueOf!T) == T));
10321         static assert(is(typeof(lvalueOf!T) == T));
10322     }
10323 
10324     static assert(!__traits(compiles, rvalueOf!int = 1));
10325     static assert( __traits(compiles, lvalueOf!byte = 127));
10326     static assert(!__traits(compiles, lvalueOf!byte = 128));
10327 }
10328 
10329 // We may want to add this as some sort of public test helper in the future in
10330 // whatever module would be appropriate for that.
10331 private template assertWithQualifiers(alias Pred, T, bool expected)
10332 {
10333     static assert(Pred!T == expected);
10334     static assert(Pred!(const T) == expected);
10335     static assert(Pred!(inout T) == expected);
10336     static assert(Pred!(immutable T) == expected);
10337     static assert(Pred!(shared T) == expected);
10338 
10339     static if (is(T == U*, U))
10340     {
10341         static assert(Pred!(const(U)*) == expected);
10342         static assert(Pred!(inout(U)*) == expected);
10343         static assert(Pred!(immutable(U)*) == expected);
10344         static assert(Pred!(shared(U)*) == expected);
10345     }
10346     else static if (is(T == U[], U))
10347     {
10348         static assert(Pred!(const(U)[]) == expected);
10349         static assert(Pred!(inout(U)[]) == expected);
10350         static assert(Pred!(immutable(U)[]) == expected);
10351         static assert(Pred!(shared(U)[]) == expected);
10352     }
10353     else static if (is(T == U[n], U, size_t n))
10354     {
10355         static assert(Pred!(const(U)[n]) == expected);
10356         static assert(Pred!(inout(U)[n]) == expected);
10357         static assert(Pred!(immutable(U)[n]) == expected);
10358         static assert(Pred!(shared(U)[n]) == expected);
10359     }
10360 }
10361 
10362 private template assertWithQualifiers(alias Pred)
10363 {
10364     alias assertWithQualifiers(T, bool expected) = .assertWithQualifiers!(Pred, T, expected);
10365 }
10366 
10367 @safe unittest
10368 {
10369     mixin assertWithQualifiers!(isPointer, int*, true);
10370     mixin assertWithQualifiers!(isPointer, int, false);
10371 
10372     alias test = assertWithQualifiers!isPointer;
10373     mixin test!(int*, true);
10374     mixin test!(int, false);
10375 }