@@ -13,7 +13,7 @@ import core.internal.convert;
13
13
14
14
// If true ensure that positive zero and negative zero have the same hash.
15
15
// typeid(float).getHash does this but historically hashOf(float) did not.
16
- private enum floatCoalesceZeroes = false ;
16
+ private enum floatCoalesceZeroes = true ;
17
17
// If true ensure that all NaNs of the same floating point type have the same hash.
18
18
// typeid(float).getHash does not do this but historically hashOf(float) did.
19
19
private enum floatCoalesceNaNs = true ;
@@ -47,12 +47,7 @@ size_t hashOf(T)(auto ref T val, size_t seed = 0) if (is(T == enum))
47
47
// CTFE ready (depends on base type). Can be merged with dynamic array hash
48
48
size_t hashOf (T)(auto ref T val, size_t seed = 0 ) if (! is (T == enum ) && __traits(isStaticArray, T))
49
49
{
50
- size_t cur_hash = seed;
51
- foreach (ref cur; val)
52
- {
53
- cur_hash = hashOf(cur, cur_hash);
54
- }
55
- return cur_hash;
50
+ return hashOf (val[], seed);
56
51
}
57
52
58
53
// dynamic array hash
@@ -64,14 +59,15 @@ if (!is(T == enum) && !is(T : typeof(null)) && is(T S: S[]) && !__traits(isStati
64
59
static if (is (ElementType == interface ) || is (ElementType == class ) ||
65
60
(is (ElementType == struct ) && ! isNonReference! ElementType) ||
66
61
((is (ElementType == struct ) || is (ElementType == union ))
67
- && is (typeof (val[0 ].toHash()) == size_t )))
62
+ && is (typeof (val[0 ].toHash()) == size_t )) ||
63
+ ((floatCoalesceZeroes || floatCoalesceNaNs) && __traits(isFloating, ElementType)))
68
64
// class or interface array or struct array with toHash(); CTFE depend on toHash() method
69
65
// also do this for arrays of structs whose hashes would be calculated in a memberwise fashion
70
66
{
71
67
size_t hash = seed;
72
68
foreach (o; val)
73
69
{
74
- hash = hashOf(o , hash);
70
+ hash = hashOf(hashOf(o) , hash); // double hashing because TypeInfo.getHash doesn't allow to pass seed value
75
71
}
76
72
return hash;
77
73
}
@@ -109,9 +105,16 @@ size_t hashOf(T)(scope const T val, size_t seed = 0) if (!is(T == enum) && __tra
109
105
{
110
106
import core.internal.traits : Unqual;
111
107
Unqual! T data = val;
112
- // Zero coalescing not supported for deprecated complex types .
108
+ // +0.0 and -0.0 become the same .
113
109
static if (floatCoalesceZeroes && is (typeof (data = 0 )))
114
- if (data == 0 ) data = 0 ; // +0.0 and -0.0 become the same.
110
+ if (data == 0 ) data = 0 ;
111
+ static if (floatCoalesceZeroes && is (typeof (data = 0. 0i)))
112
+ if (data == 0. 0i) data = 0. 0i;
113
+ static if (floatCoalesceZeroes && is (typeof (data = 0.0 + 0. 0i)))
114
+ {
115
+ if (data.re == 0.0 ) data = 0.0 + (data.im * 1. 0i);
116
+ if (data.im == 0. 0i) data = data.re + 0. 0i;
117
+ }
115
118
static if (floatCoalesceNaNs)
116
119
if (data != data) data = T.nan; // All NaN patterns become the same.
117
120
}
@@ -313,6 +316,12 @@ unittest
313
316
int * a = null ;
314
317
}
315
318
319
+ static struct Plain
320
+ {
321
+ int a = 1 ;
322
+ int b = 2 ;
323
+ }
324
+
316
325
interface IBoo
317
326
{
318
327
void boo ();
@@ -362,7 +371,8 @@ unittest
362
371
enum realexpr = 7.88 ;
363
372
enum raexpr = [8.99L + 86i, 3.12L + 99i, 5.66L + 12i];
364
373
enum nullexpr = null ;
365
-
374
+ enum plstr = Plain();
375
+ enum plarrstr = [Plain(), Plain(), Plain()];
366
376
// No CTFE:
367
377
Boom rstructexpr = Boom();
368
378
Boom[] rstrarrexpr = [Boom(), Boom(), Boom()];
@@ -406,6 +416,9 @@ unittest
406
416
enum h28 = realexpr.hashOf();
407
417
enum h29 = raexpr.hashOf();
408
418
enum h30 = nullexpr.hashOf();
419
+ enum h31 = plstr.hashOf();
420
+ enum h32 = plarrstr.hashOf();
421
+ enum h33 = hashOf(cast (Plain[3 ])plarrstr);
409
422
410
423
auto v1 = dexpr;
411
424
auto v2 = fexpr;
@@ -431,14 +444,17 @@ unittest
431
444
auto v22 = cast (IBoo[3 ])[cast (IBoo)new Boo, cast (IBoo)new Boo, cast (IBoo)new Boo];
432
445
auto v23 = cast (Bar [3 ])vsaexpr;
433
446
auto v30 = null ;
447
+ auto v31 = plstr;
448
+ auto v32 = plarrstr;
449
+ auto v33 = cast (Plain[3 ])plarrstr;
434
450
435
451
// NO CTFE:
436
- /* auto v24 = rstructexpr;
452
+ auto v24 = rstructexpr;
437
453
auto v25 = rstrarrexpr;
438
454
auto v26 = dgexpr;
439
455
auto v27 = ptrexpr;
440
456
auto v28 = realexpr;
441
- auto v29 = raexpr;*/
457
+ auto v29 = raexpr;
442
458
443
459
// runtime hashes
444
460
auto rth1 = hashOf(v1);
@@ -465,13 +481,17 @@ unittest
465
481
auto rth22 = hashOf(v22);
466
482
auto rth23 = hashOf(v23);
467
483
auto rth30 = hashOf(v30);
468
- /* / /NO CTFE:
484
+ // NO CTFE:
469
485
auto rth24 = hashOf(v24);
470
486
auto rth25 = hashOf(v25);
471
487
auto rth26 = hashOf(v26);
472
488
auto rth27 = hashOf(v27);
473
489
auto rth28 = hashOf(v28);
474
- auto rth29 = hashOf(v29);*/
490
+ auto rth29 = hashOf(v29);
491
+
492
+ auto rth31 = hashOf(v31);
493
+ auto rth32 = hashOf(v32);
494
+ auto rth33 = hashOf(v33);
475
495
476
496
assert (h1 == rth1);
477
497
assert (h2 == rth2);
@@ -503,8 +523,84 @@ unittest
503
523
assert(h28 == rth28);
504
524
assert(h29 == rth29);*/
505
525
assert (h30 == rth30);
526
+ assert (h31 == rth31);
527
+ assert (h32 == rth32);
528
+ assert (h33 == rth33);
506
529
507
530
assert (hashOf(null , 0 ) != hashOf(null , 123456789 )); // issue 18932
531
+
532
+ static size_t tiHashOf (T)(T var)
533
+ {
534
+ return typeid (T).getHash(&var);
535
+ }
536
+
537
+ auto tih1 = tiHashOf(v1);
538
+ auto tih2 = tiHashOf(v2);
539
+ auto tih3 = tiHashOf(v3);
540
+ auto tih4 = tiHashOf(v4);
541
+ auto tih5 = tiHashOf(v5);
542
+ auto tih6 = tiHashOf(v6);
543
+ auto tih7 = tiHashOf(v7);
544
+ auto tih8 = tiHashOf(v8);
545
+ auto tih9 = tiHashOf(v9);
546
+ auto tih10 = tiHashOf(v10);
547
+ auto tih11 = tiHashOf(v11);
548
+ auto tih12 = tiHashOf(v12);
549
+ auto tih13 = tiHashOf(v13);
550
+ auto tih14 = tiHashOf(v14);
551
+ auto tih15 = tiHashOf(v15);
552
+ auto tih16 = tiHashOf(v16);
553
+ auto tih17 = tiHashOf(v17);
554
+ auto tih18 = tiHashOf(v18);
555
+ auto tih19 = tiHashOf(v19);
556
+ auto tih20 = tiHashOf(v20);
557
+ auto tih21 = tiHashOf(v21);
558
+ auto tih22 = tiHashOf(v22);
559
+ auto tih23 = tiHashOf(v23);
560
+ auto tih24 = tiHashOf(v24);
561
+ auto tih25 = tiHashOf(v25);
562
+ auto tih26 = tiHashOf(v26);
563
+ auto tih27 = tiHashOf(v27);
564
+ auto tih28 = tiHashOf(v28);
565
+ auto tih29 = tiHashOf(v29);
566
+ auto tih30 = tiHashOf(v30);
567
+ auto tih31 = tiHashOf(v31);
568
+ auto tih32 = tiHashOf(v32);
569
+ auto tih33 = tiHashOf(v33);
570
+
571
+ assert (tih1 == rth1);
572
+ assert (tih2 == rth2);
573
+ assert (tih3 == rth3);
574
+ assert (tih4 == rth4);
575
+ assert (tih5 == rth5);
576
+ assert (tih6 == rth6);
577
+ assert (tih7 == rth7);
578
+ assert (tih8 == rth8);
579
+ assert (tih9 == rth9);
580
+ // assert(tih10 == rth10); // need compiler-generated __xtoHash changes
581
+ assert (tih11 == rth11);
582
+ assert (tih12 == rth12);
583
+ assert (tih13 == rth13);
584
+ assert (tih14 == rth14);
585
+ assert (tih15 == rth15);
586
+ assert (tih16 == rth16);
587
+ assert (tih17 == rth17);
588
+ assert (tih18 == rth18);
589
+ // assert(tih19 == rth19); // need compiler-generated __xtoHash changes
590
+ assert (tih20 == rth20);
591
+ assert (tih21 == rth21);
592
+ assert (tih22 == rth22);
593
+ // assert(tih23 == rth23); // need compiler-generated __xtoHash changes
594
+ // assert(tih24 == rth24);
595
+ // assert(tih25 == rth25);
596
+ assert (tih26 == rth26);
597
+ assert (tih27 == rth27);
598
+ assert (tih28 == rth28);
599
+ assert (tih29 == rth29);
600
+ assert (tih30 == rth30);
601
+ assert (tih31 == rth31);
602
+ assert (tih32 == rth32);
603
+ assert (tih33 == rth33);
508
604
}
509
605
510
606
0 commit comments