@@ -256,6 +256,8 @@ private enum hasPostblit(T) = __traits(hasPostblit, T);
256256
257257private enum isInout (T) = is (T == inout );
258258
259+ private enum memberName (size_t tid) = " values_" ~ toCtString! tid;
260+
259261// Workaround for dlang issue 19669
260262private enum haveDip1000 = __traits(compiles, () @safe {
261263 int x;
@@ -300,45 +302,41 @@ private:
300302
301303 union Storage
302304 {
303- // Workaround for dlang issue 20068
304- template memberName (T)
305- if (IndexOf! (T, Types) >= 0 )
306- {
307- enum tid = IndexOf! (T, Types);
308- mixin (" enum memberName = `values_" , toCtString! tid, " `;" );
309- }
310-
311- static foreach (T; Types) {
312- mixin (" T " , memberName! T, " ;" );
305+ static foreach (tid, T; Types) {
306+ /+
307+ Giving these fields individual names makes it possible to use brace
308+ initialization for Storage.
309+ +/
310+ mixin (" T " , memberName! tid, " ;" );
313311 }
314312 }
315313
316314 Storage storage;
317315 Tag tag;
318316
319317 /**
320- * Accesses the value stored in a SumType.
318+ * Accesses the value stored in a SumType by its index .
321319 *
322320 * This method is memory-safe, provided that:
323321 *
324322 * 1. A SumType's tag is always accurate.
325- * 2. A SumType cannot be assigned to in @safe code if that assignment
326- * could cause unsafe aliasing.
323+ * 2. A SumType's value cannot be unsafely aliased in @safe code.
327324 *
328325 * All code that accesses a SumType's tag or storage directly, including
329326 * @safe code in this module, must be manually checked to ensure that it
330327 * does not violate either of the above requirements.
331328 */
332329 @trusted
333- ref inout (T) get (T)() inout
334- if (IndexOf! (T, Types) >= 0 )
330+ // Explicit return type omitted
331+ // Workaround for https://github.com/dlang/dmd/issues/20549
332+ ref get (size_t tid)() inout
333+ if (tid < Types.length)
335334 {
336- enum tid = IndexOf! (T, Types);
337335 assert (tag == tid,
338- " This `" ~ SumType.stringof ~
339- " ` does not contain a(n) `" ~ T .stringof ~ " `"
336+ " This `" ~ SumType.stringof ~ " ` " ~
337+ " does not contain a(n) `" ~ Types[tid] .stringof ~ " `"
340338 );
341- return __traits (getMember, storage, Storage.memberName ! T) ;
339+ return storage.tupleof[tid] ;
342340 }
343341
344342public :
@@ -351,9 +349,9 @@ public:
351349
352350 static if (isCopyable! T) {
353351 // Workaround for dlang issue 21542
354- __traits ( getMember , storage, Storage.memberName ! T) = __ctfe ? value : forward! value;
352+ storage.tupleof[tid] = __ctfe ? value : forward! value;
355353 } else {
356- __traits ( getMember , storage, Storage.memberName ! T) = forward! value;
354+ storage.tupleof[tid] = forward! value;
357355 }
358356
359357 tag = tid;
@@ -365,7 +363,7 @@ public:
365363 // / ditto
366364 this (const (T) value) const
367365 {
368- __traits ( getMember , storage, Storage.memberName ! T) = value;
366+ storage.tupleof[tid] = value;
369367 tag = tid;
370368 }
371369 }
@@ -378,7 +376,7 @@ public:
378376 // / ditto
379377 this (immutable (T) value) immutable
380378 {
381- __traits ( getMember , storage, Storage.memberName ! T) = value;
379+ storage.tupleof[tid] = value;
382380 tag = tid;
383381 }
384382 }
@@ -392,7 +390,7 @@ public:
392390 this (Value)(Value value) inout
393391 if (is (Value == DeducedParameterType! (inout (T))))
394392 {
395- __traits ( getMember , storage, Storage.memberName ! T) = value;
393+ storage.tupleof[tid] = value;
396394 tag = tid;
397395 }
398396 }
@@ -414,10 +412,9 @@ public:
414412 storage = other.match! ((ref value) {
415413 alias OtherTypes = Map! (InoutOf, Types);
416414 enum tid = IndexOf! (typeof (value), OtherTypes);
417- alias T = Types[tid];
418415
419416 mixin (" inout(Storage) newStorage = { " ,
420- Storage. memberName! T , " : value" ,
417+ memberName! tid , " : value" ,
421418 " };" );
422419
423420 return newStorage;
@@ -431,10 +428,10 @@ public:
431428 this (ref SumType other)
432429 {
433430 storage = other.match! ((ref value) {
434- alias T = typeof (value);
431+ enum tid = IndexOf ! ( typeof (value), Types );
435432
436433 mixin (" Storage newStorage = { " ,
437- Storage. memberName! T , " : value" ,
434+ memberName! tid , " : value" ,
438435 " };" );
439436
440437 return newStorage;
@@ -453,10 +450,9 @@ public:
453450 storage = other.match! ((ref value) {
454451 alias OtherTypes = Map! (ConstOf, Types);
455452 enum tid = IndexOf! (typeof (value), OtherTypes);
456- alias T = Types[tid];
457453
458454 mixin (" const(Storage) newStorage = { " ,
459- Storage. memberName! T , " : value" ,
455+ memberName! tid , " : value" ,
460456 " };" );
461457
462458 return newStorage;
@@ -475,10 +471,9 @@ public:
475471 storage = other.match! ((ref value) {
476472 alias OtherTypes = Map! (ImmutableOf, Types);
477473 enum tid = IndexOf! (typeof (value), OtherTypes);
478- alias T = Types[tid];
479474
480475 mixin (" immutable(Storage) newStorage = { " ,
481- Storage. memberName! T , " : value" ,
476+ memberName! tid , " : value" ,
482477 " };" );
483478
484479 return newStorage;
@@ -549,12 +544,13 @@ public:
549544 this .match! destroyIfOwner;
550545
551546 static if (isCopyable! T) {
547+ // Workaround for dlang issue 21542
552548 mixin (" Storage newStorage = { " ,
553- Storage. memberName! T , " : __ctfe ? rhs : forward!rhs" ,
549+ memberName! tid , " : __ctfe ? rhs : forward!rhs" ,
554550 " };" );
555551 } else {
556552 mixin (" Storage newStorage = { " ,
557- Storage. memberName! T , " : forward!rhs" ,
553+ memberName! tid , " : forward!rhs" ,
558554 " };" );
559555 }
560556
@@ -1005,7 +1001,7 @@ version (D_BetterC) {} else
10051001 alias MySum = SumType! (ubyte , void * [2 ]);
10061002
10071003 MySum x = [null , cast (void * ) 0x12345678 ];
1008- void ** p = &x.get ! ( void * [ 2 ]) [1 ];
1004+ void ** p = &x.get ! 1 [1 ];
10091005 x = ubyte (123 );
10101006
10111007 assert (* p != cast (void * ) 0x12345678 );
@@ -1034,8 +1030,8 @@ version (D_BetterC) {} else
10341030 } catch (Exception e) {}
10351031
10361032 assert (
1037- (x.tag == 0 && x.get ! A .value == 123 ) ||
1038- (x.tag == 1 && x.get ! B .value == 456 )
1033+ (x.tag == 0 && x.get ! 0 . value == 123 ) ||
1034+ (x.tag == 1 && x.get ! 1 . value == 456 )
10391035 );
10401036}
10411037
@@ -1093,8 +1089,8 @@ version (D_BetterC) {} else
10931089 SumType! (S[1 ]) x = [S(0 )];
10941090 SumType! (S[1 ]) y = x;
10951091
1096- auto xval = x.get ! (S[ 1 ]) [0 ].n;
1097- auto yval = y.get ! (S[ 1 ]) [0 ].n;
1092+ auto xval = x.get ! 0 [0 ].n;
1093+ auto yval = y.get ! 0 [0 ].n;
10981094
10991095 assert (xval != yval);
11001096}
@@ -1169,8 +1165,8 @@ version (D_BetterC) {} else
11691165 SumType! S y;
11701166 y = x;
11711167
1172- auto xval = x.get ! S .n;
1173- auto yval = y.get ! S .n;
1168+ auto xval = x.get ! 0 . n;
1169+ auto yval = y.get ! 0 . n;
11741170
11751171 assert (xval != yval);
11761172}
@@ -1241,8 +1237,8 @@ version (D_BetterC) {} else
12411237 SumType! S x = S();
12421238 SumType! S y = x;
12431239
1244- auto xval = x.get ! S .n;
1245- auto yval = y.get ! S .n;
1240+ auto xval = x.get ! 0 . n;
1241+ auto yval = y.get ! 0 . n;
12461242
12471243 assert (xval != yval);
12481244}
@@ -1783,10 +1779,10 @@ private template matchImpl(Flag!"exhaustive" exhaustive, handlers...)
17831779 * argument's tag, so there's no need to use TagTuple.
17841780 */
17851781 enum handlerArgs (size_t caseId) =
1786- " args[0].get!(SumTypes[0].Types[ " ~ toCtString! caseId ~ " ] )()" ;
1782+ " args[0].get!(" ~ toCtString! caseId ~ " )()" ;
17871783
17881784 alias valueTypes (size_t caseId) =
1789- typeof (args[0 ].get ! (SumTypes[ 0 ].Types[ caseId] )());
1785+ typeof (args[0 ].get ! (caseId)());
17901786
17911787 enum numCases = SumTypes[0 ].Types.length;
17921788 // Multiple dispatch (slow path)
@@ -1810,9 +1806,7 @@ private template matchImpl(Flag!"exhaustive" exhaustive, handlers...)
18101806
18111807 template getType (size_t i)
18121808 {
1813- enum tid = tags[i];
1814- alias T = SumTypes[i].Types[tid];
1815- alias getType = typeof (args[i].get ! T());
1809+ alias getType = typeof (args[i].get ! (tags[i])());
18161810 }
18171811
18181812 alias valueTypes = Map! (getType, Iota! (tags.length));
@@ -2015,8 +2009,7 @@ template handlerArgs(size_t caseId, typeCounts...)
20152009 static foreach (i; 0 .. tags.length) {
20162010 handlerArgs = AliasSeq! (
20172011 handlerArgs,
2018- " args[" ~ toCtString! i ~ " ].get!(SumTypes[" ~ toCtString! i ~ " ]" ~
2019- " .Types[" ~ toCtString! (tags[i]) ~ " ])(), "
2012+ " args[" ~ toCtString! i ~ " ].get!(" ~ toCtString! (tags[i]) ~ " )(), "
20202013 );
20212014 }
20222015}
@@ -2264,7 +2257,7 @@ version (D_Exceptions)
22642257 (ref double d) { d *= 2 ; }
22652258 );
22662259
2267- assert (value.get ! double .isClose(6.28 ));
2260+ assert (value.get ! 1 . isClose(6.28 ));
22682261}
22692262
22702263// Handlers that return by ref
0 commit comments