@@ -254,6 +254,8 @@ private enum hasPostblit(T) = __traits(hasPostblit, T);
254
254
255
255
private enum isInout (T) = is (T == inout );
256
256
257
+ private enum memberName (size_t tid) = " values_" ~ toCtString! tid;
258
+
257
259
/**
258
260
* A [tagged union](https://en.wikipedia.org/wiki/Tagged_union) that can hold a
259
261
* single value from any of a specified set of types.
@@ -290,45 +292,42 @@ private:
290
292
291
293
union Storage
292
294
{
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
- }
300
295
301
- static foreach (T; Types)
296
+ static foreach (tid, T; Types)
302
297
{
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, " ;" );
304
303
}
305
304
}
306
305
307
306
Storage storage;
308
307
Tag tag;
309
308
310
- /* Accesses the value stored in a SumType.
309
+ /* Accesses the value stored in a SumType by its index .
311
310
*
312
311
* This method is memory-safe, provided that:
313
312
*
314
313
* 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.
317
315
*
318
316
* All code that accesses a SumType's tag or storage directly, including
319
317
* @safe code in this module, must be manually checked to ensure that it
320
318
* does not violate either of the above requirements.
321
319
*/
322
320
@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)
325
325
{
326
- enum tid = IndexOf! (T, Types);
327
326
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 ~ " `"
330
329
);
331
- return __traits (getMember, storage, Storage.memberName ! T) ;
330
+ return storage.tupleof[tid] ;
332
331
}
333
332
334
333
public :
@@ -363,11 +362,11 @@ public:
363
362
static if (isCopyable! T)
364
363
{
365
364
// 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;
367
366
}
368
367
else
369
368
{
370
- __traits ( getMember , storage, Storage.memberName ! T) = forward! value;
369
+ storage.tupleof[tid] = forward! value;
371
370
}
372
371
373
372
tag = tid;
@@ -380,7 +379,7 @@ public:
380
379
// / ditto
381
380
this (const (T) value) const
382
381
{
383
- __traits ( getMember , storage, Storage.memberName ! T) = value;
382
+ storage.tupleof[tid] = value;
384
383
tag = tid;
385
384
}
386
385
}
@@ -397,7 +396,7 @@ public:
397
396
// / ditto
398
397
this (immutable (T) value) immutable
399
398
{
400
- __traits ( getMember , storage, Storage.memberName ! T) = value;
399
+ storage.tupleof[tid] = value;
401
400
tag = tid;
402
401
}
403
402
}
@@ -415,7 +414,7 @@ public:
415
414
this (Value)(Value value) inout
416
415
if (is (Value == DeducedParameterType! (inout (T))))
417
416
{
418
- __traits ( getMember , storage, Storage.memberName ! T) = value;
417
+ storage.tupleof[tid] = value;
419
418
tag = tid;
420
419
}
421
420
}
@@ -442,10 +441,9 @@ public:
442
441
storage = other.match! ((ref value) {
443
442
alias OtherTypes = Map! (InoutOf, Types);
444
443
enum tid = IndexOf! (typeof (value), OtherTypes);
445
- alias T = Types[tid];
446
444
447
445
mixin (" inout(Storage) newStorage = { " ,
448
- Storage. memberName! T , " : value" ,
446
+ memberName! tid , " : value" ,
449
447
" };" );
450
448
451
449
return newStorage;
@@ -462,10 +460,10 @@ public:
462
460
this (ref SumType other)
463
461
{
464
462
storage = other.match! ((ref value) {
465
- alias T = typeof (value);
463
+ enum tid = IndexOf ! ( typeof (value), Types );
466
464
467
465
mixin (" Storage newStorage = { " ,
468
- Storage. memberName! T , " : value" ,
466
+ memberName! tid , " : value" ,
469
467
" };" );
470
468
471
469
return newStorage;
@@ -487,10 +485,9 @@ public:
487
485
storage = other.match! ((ref value) {
488
486
alias OtherTypes = Map! (ConstOf, Types);
489
487
enum tid = IndexOf! (typeof (value), OtherTypes);
490
- alias T = Types[tid];
491
488
492
489
mixin (" const(Storage) newStorage = { " ,
493
- Storage. memberName! T , " : value" ,
490
+ memberName! tid , " : value" ,
494
491
" };" );
495
492
496
493
return newStorage;
@@ -512,10 +509,9 @@ public:
512
509
storage = other.match! ((ref value) {
513
510
alias OtherTypes = Map! (ImmutableOf, Types);
514
511
enum tid = IndexOf! (typeof (value), OtherTypes);
515
- alias T = Types[tid];
516
512
517
513
mixin (" immutable(Storage) newStorage = { " ,
518
- Storage. memberName! T , " : value" ,
514
+ memberName! tid , " : value" ,
519
515
" };" );
520
516
521
517
return newStorage;
@@ -637,13 +633,13 @@ public:
637
633
{
638
634
// Workaround for https://issues.dlang.org/show_bug.cgi?id=21542
639
635
mixin (" Storage newStorage = { " ,
640
- Storage. memberName! T , " : __ctfe ? rhs : forward!rhs" ,
636
+ memberName! tid , " : __ctfe ? rhs : forward!rhs" ,
641
637
" };" );
642
638
}
643
639
else
644
640
{
645
641
mixin (" Storage newStorage = { " ,
646
- Storage. memberName! T , " : forward!rhs" ,
642
+ memberName! tid , " : forward!rhs" ,
647
643
" };" );
648
644
}
649
645
@@ -1146,7 +1142,7 @@ version (D_BetterC) {} else
1146
1142
alias MySum = SumType! (ubyte , void * [2 ]);
1147
1143
1148
1144
MySum x = [null , cast (void * ) 0x12345678 ];
1149
- void ** p = &x.get ! ( void * [ 2 ]) [1 ];
1145
+ void ** p = &x.get ! 1 [1 ];
1150
1146
x = ubyte (123 );
1151
1147
1152
1148
assert (* p != cast (void * ) 0x12345678 );
@@ -1178,8 +1174,8 @@ version (D_BetterC) {} else
1178
1174
catch (Exception e) {}
1179
1175
1180
1176
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 )
1183
1179
);
1184
1180
}
1185
1181
@@ -1238,8 +1234,8 @@ version (D_BetterC) {} else
1238
1234
SumType! (S[1 ]) x = [S(0 )];
1239
1235
SumType! (S[1 ]) y = x;
1240
1236
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;
1243
1239
1244
1240
assert (xval != yval);
1245
1241
}
@@ -1324,8 +1320,8 @@ version (D_BetterC) {} else
1324
1320
SumType! S y;
1325
1321
y = x;
1326
1322
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;
1329
1325
1330
1326
assert (xval != yval);
1331
1327
}
@@ -1399,8 +1395,8 @@ version (D_BetterC) {} else
1399
1395
SumType! S x = S();
1400
1396
SumType! S y = x;
1401
1397
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;
1404
1400
1405
1401
assert (xval != yval);
1406
1402
}
@@ -1872,10 +1868,10 @@ private template matchImpl(Flag!"exhaustive" exhaustive, handlers...)
1872
1868
* argument's tag, so there's no need for TagTuple.
1873
1869
*/
1874
1870
enum handlerArgs (size_t caseId) =
1875
- " args[0].get!(SumTypes[0].Types[ " ~ toCtString! caseId ~ " ] )()" ;
1871
+ " args[0].get!(" ~ toCtString! caseId ~ " )()" ;
1876
1872
1877
1873
alias valueTypes (size_t caseId) =
1878
- typeof (args[0 ].get ! (SumTypes[ 0 ].Types[ caseId] )());
1874
+ typeof (args[0 ].get ! (caseId)());
1879
1875
1880
1876
enum numCases = SumTypes[0 ].Types.length;
1881
1877
}
@@ -1901,9 +1897,7 @@ private template matchImpl(Flag!"exhaustive" exhaustive, handlers...)
1901
1897
1902
1898
template getType (size_t i)
1903
1899
{
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])());
1907
1901
}
1908
1902
1909
1903
alias valueTypes = Map! (getType, Iota! (tags.length));
@@ -2128,8 +2122,7 @@ private template handlerArgs(size_t caseId, typeCounts...)
2128
2122
{
2129
2123
handlerArgs = AliasSeq! (
2130
2124
handlerArgs,
2131
- " args[" ~ toCtString! i ~ " ].get!(SumTypes[" ~ toCtString! i ~ " ]" ~
2132
- " .Types[" ~ toCtString! (tags[i]) ~ " ])(), "
2125
+ " args[" ~ toCtString! i ~ " ].get!(" ~ toCtString! (tags[i]) ~ " )(), "
2133
2126
);
2134
2127
}
2135
2128
}
@@ -2393,7 +2386,7 @@ version (D_Exceptions)
2393
2386
(ref double d) { d *= 2 ; }
2394
2387
);
2395
2388
2396
- assert (value.get ! double .isClose(6.28 ));
2389
+ assert (value.get ! 1 . isClose(6.28 ));
2397
2390
}
2398
2391
2399
2392
// Unreachable handlers
0 commit comments