@@ -254,6 +254,8 @@ private enum hasPostblit(T) = __traits(hasPostblit, T);
254254
255255private enum isInout (T) = is (T == inout );
256256
257+ private enum memberName (size_t tid) = " values_" ~ toCtString! tid;
258+
257259/**
258260 * A [tagged union](https://en.wikipedia.org/wiki/Tagged_union) that can hold a
259261 * single value from any of a specified set of types.
@@ -290,45 +292,42 @@ private:
290292
291293 union Storage
292294 {
293- // Workaround for https://issues.dlang.org/show_bug.cgi?id=20068
294- template memberName (T)
295- if (IndexOf! (T, Types) >= 0 )
296- {
297- enum tid = IndexOf! (T, Types);
298- mixin (" enum memberName = `values_" , toCtString! tid, " `;" );
299- }
300295
301- static foreach (T; Types)
296+ static foreach (tid, T; Types)
302297 {
303- mixin (" T " , memberName! T, " ;" );
298+ /+
299+ Giving these fields individual names makes it possible to use brace
300+ initialization for Storage.
301+ +/
302+ mixin (" T " , memberName! tid, " ;" );
304303 }
305304 }
306305
307306 Storage storage;
308307 Tag tag;
309308
310- /* Accesses the value stored in a SumType.
309+ /* Accesses the value stored in a SumType by its index .
311310 *
312311 * This method is memory-safe, provided that:
313312 *
314313 * 1. A SumType's tag is always accurate.
315- * 2. A SumType cannot be assigned to in @safe code if that assignment
316- * could cause unsafe aliasing.
314+ * 2. A SumType's value cannot be unsafely aliased in @safe code.
317315 *
318316 * All code that accesses a SumType's tag or storage directly, including
319317 * @safe code in this module, must be manually checked to ensure that it
320318 * does not violate either of the above requirements.
321319 */
322320 @trusted
323- ref inout (T) get (T)() inout
324- if (IndexOf! (T, Types) >= 0 )
321+ // Explicit return type omitted
322+ // Workaround for https://github.com/dlang/dmd/issues/20549
323+ ref get (size_t tid)() inout
324+ if (tid < Types.length)
325325 {
326- enum tid = IndexOf! (T, Types);
327326 assert (tag == tid,
328- " This `" ~ SumType.stringof ~
329- " ` does not contain a(n) `" ~ T .stringof ~ " `"
327+ " This `" ~ SumType.stringof ~ " ` " ~
328+ " does not contain a(n) `" ~ Types[tid] .stringof ~ " `"
330329 );
331- return __traits (getMember, storage, Storage.memberName ! T) ;
330+ return storage.tupleof[tid] ;
332331 }
333332
334333public :
@@ -363,11 +362,11 @@ public:
363362 static if (isCopyable! T)
364363 {
365364 // Workaround for https://issues.dlang.org/show_bug.cgi?id=21542
366- __traits ( getMember , storage, Storage.memberName ! T) = __ctfe ? value : forward! value;
365+ storage.tupleof[tid] = __ctfe ? value : forward! value;
367366 }
368367 else
369368 {
370- __traits ( getMember , storage, Storage.memberName ! T) = forward! value;
369+ storage.tupleof[tid] = forward! value;
371370 }
372371
373372 tag = tid;
@@ -380,7 +379,7 @@ public:
380379 // / ditto
381380 this (const (T) value) const
382381 {
383- __traits ( getMember , storage, Storage.memberName ! T) = value;
382+ storage.tupleof[tid] = value;
384383 tag = tid;
385384 }
386385 }
@@ -397,7 +396,7 @@ public:
397396 // / ditto
398397 this (immutable (T) value) immutable
399398 {
400- __traits ( getMember , storage, Storage.memberName ! T) = value;
399+ storage.tupleof[tid] = value;
401400 tag = tid;
402401 }
403402 }
@@ -415,7 +414,7 @@ public:
415414 this (Value)(Value value) inout
416415 if (is (Value == DeducedParameterType! (inout (T))))
417416 {
418- __traits ( getMember , storage, Storage.memberName ! T) = value;
417+ storage.tupleof[tid] = value;
419418 tag = tid;
420419 }
421420 }
@@ -442,10 +441,9 @@ public:
442441 storage = other.match! ((ref value) {
443442 alias OtherTypes = Map! (InoutOf, Types);
444443 enum tid = IndexOf! (typeof (value), OtherTypes);
445- alias T = Types[tid];
446444
447445 mixin (" inout(Storage) newStorage = { " ,
448- Storage. memberName! T , " : value" ,
446+ memberName! tid , " : value" ,
449447 " };" );
450448
451449 return newStorage;
@@ -462,10 +460,10 @@ public:
462460 this (ref SumType other)
463461 {
464462 storage = other.match! ((ref value) {
465- alias T = typeof (value);
463+ enum tid = IndexOf ! ( typeof (value), Types );
466464
467465 mixin (" Storage newStorage = { " ,
468- Storage. memberName! T , " : value" ,
466+ memberName! tid , " : value" ,
469467 " };" );
470468
471469 return newStorage;
@@ -487,10 +485,9 @@ public:
487485 storage = other.match! ((ref value) {
488486 alias OtherTypes = Map! (ConstOf, Types);
489487 enum tid = IndexOf! (typeof (value), OtherTypes);
490- alias T = Types[tid];
491488
492489 mixin (" const(Storage) newStorage = { " ,
493- Storage. memberName! T , " : value" ,
490+ memberName! tid , " : value" ,
494491 " };" );
495492
496493 return newStorage;
@@ -512,10 +509,9 @@ public:
512509 storage = other.match! ((ref value) {
513510 alias OtherTypes = Map! (ImmutableOf, Types);
514511 enum tid = IndexOf! (typeof (value), OtherTypes);
515- alias T = Types[tid];
516512
517513 mixin (" immutable(Storage) newStorage = { " ,
518- Storage. memberName! T , " : value" ,
514+ memberName! tid , " : value" ,
519515 " };" );
520516
521517 return newStorage;
@@ -637,13 +633,13 @@ public:
637633 {
638634 // Workaround for https://issues.dlang.org/show_bug.cgi?id=21542
639635 mixin (" Storage newStorage = { " ,
640- Storage. memberName! T , " : __ctfe ? rhs : forward!rhs" ,
636+ memberName! tid , " : __ctfe ? rhs : forward!rhs" ,
641637 " };" );
642638 }
643639 else
644640 {
645641 mixin (" Storage newStorage = { " ,
646- Storage. memberName! T , " : forward!rhs" ,
642+ memberName! tid , " : forward!rhs" ,
647643 " };" );
648644 }
649645
@@ -1146,7 +1142,7 @@ version (D_BetterC) {} else
11461142 alias MySum = SumType! (ubyte , void * [2 ]);
11471143
11481144 MySum x = [null , cast (void * ) 0x12345678 ];
1149- void ** p = &x.get ! ( void * [ 2 ]) [1 ];
1145+ void ** p = &x.get ! 1 [1 ];
11501146 x = ubyte (123 );
11511147
11521148 assert (* p != cast (void * ) 0x12345678 );
@@ -1178,8 +1174,8 @@ version (D_BetterC) {} else
11781174 catch (Exception e) {}
11791175
11801176 assert (
1181- (x.tag == 0 && x.get ! A .value == 123 ) ||
1182- (x.tag == 1 && x.get ! B .value == 456 )
1177+ (x.tag == 0 && x.get ! 0 . value == 123 ) ||
1178+ (x.tag == 1 && x.get ! 1 . value == 456 )
11831179 );
11841180}
11851181
@@ -1238,8 +1234,8 @@ version (D_BetterC) {} else
12381234 SumType! (S[1 ]) x = [S(0 )];
12391235 SumType! (S[1 ]) y = x;
12401236
1241- auto xval = x.get ! (S[ 1 ]) [0 ].n;
1242- auto yval = y.get ! (S[ 1 ]) [0 ].n;
1237+ auto xval = x.get ! 0 [0 ].n;
1238+ auto yval = y.get ! 0 [0 ].n;
12431239
12441240 assert (xval != yval);
12451241}
@@ -1324,8 +1320,8 @@ version (D_BetterC) {} else
13241320 SumType! S y;
13251321 y = x;
13261322
1327- auto xval = x.get ! S .n;
1328- auto yval = y.get ! S .n;
1323+ auto xval = x.get ! 0 . n;
1324+ auto yval = y.get ! 0 . n;
13291325
13301326 assert (xval != yval);
13311327}
@@ -1399,8 +1395,8 @@ version (D_BetterC) {} else
13991395 SumType! S x = S();
14001396 SumType! S y = x;
14011397
1402- auto xval = x.get ! S .n;
1403- auto yval = y.get ! S .n;
1398+ auto xval = x.get ! 0 . n;
1399+ auto yval = y.get ! 0 . n;
14041400
14051401 assert (xval != yval);
14061402}
@@ -1872,10 +1868,10 @@ private template matchImpl(Flag!"exhaustive" exhaustive, handlers...)
18721868 * argument's tag, so there's no need for TagTuple.
18731869 */
18741870 enum handlerArgs (size_t caseId) =
1875- " args[0].get!(SumTypes[0].Types[ " ~ toCtString! caseId ~ " ] )()" ;
1871+ " args[0].get!(" ~ toCtString! caseId ~ " )()" ;
18761872
18771873 alias valueTypes (size_t caseId) =
1878- typeof (args[0 ].get ! (SumTypes[ 0 ].Types[ caseId] )());
1874+ typeof (args[0 ].get ! (caseId)());
18791875
18801876 enum numCases = SumTypes[0 ].Types.length;
18811877 }
@@ -1901,9 +1897,7 @@ private template matchImpl(Flag!"exhaustive" exhaustive, handlers...)
19011897
19021898 template getType (size_t i)
19031899 {
1904- enum tid = tags[i];
1905- alias T = SumTypes[i].Types[tid];
1906- alias getType = typeof (args[i].get ! T());
1900+ alias getType = typeof (args[i].get ! (tags[i])());
19071901 }
19081902
19091903 alias valueTypes = Map! (getType, Iota! (tags.length));
@@ -2128,8 +2122,7 @@ private template handlerArgs(size_t caseId, typeCounts...)
21282122 {
21292123 handlerArgs = AliasSeq! (
21302124 handlerArgs,
2131- " args[" ~ toCtString! i ~ " ].get!(SumTypes[" ~ toCtString! i ~ " ]" ~
2132- " .Types[" ~ toCtString! (tags[i]) ~ " ])(), "
2125+ " args[" ~ toCtString! i ~ " ].get!(" ~ toCtString! (tags[i]) ~ " )(), "
21332126 );
21342127 }
21352128}
@@ -2393,7 +2386,7 @@ version (D_Exceptions)
23932386 (ref double d) { d *= 2 ; }
23942387 );
23952388
2396- assert (value.get ! double .isClose(6.28 ));
2389+ assert (value.get ! 1 . isClose(6.28 ));
23972390}
23982391
23992392// Unreachable handlers
0 commit comments