1 // { dg-prune-output "Warning: struct HasNonConstToHash has method toHash" }
2 // { dg-prune-output "HasNonConstToHash.toHash defined here:" }
main()3 void main()
4 {
5 issue19562();
6 issue15111();
7 issues16654And16764();
8 issue18918();
9 issue18925();
10 issue19005();
11 issue19204();
12 issue19262();
13 issue19282();
14 issue19332(); // Support might be removed in the future!
15 issue19568();
16 issue19582();
17 issue20034();
18 issue21642();
19 issue22024();
20 issue22076();
21 testTypeInfoArrayGetHash1();
22 testTypeInfoArrayGetHash2();
23 pr2243();
24 }
25
26 /// Check hashOf an array of void pointers or delegates is @safe.
issue19562()27 void issue19562() @nogc nothrow pure @safe
28 {
29 void*[10] val;
30 size_t h = hashOf(val[]);
31
32 alias D = void delegate();
33 D[10] ds;
34 h = hashOf(ds[]);
35 }
36
37 /// hashOf was failing for structs that had an `alias this` to a dynamic array.
issue15111()38 void issue15111()
39 {
40 void testAlias(T)()
41 {
42 static struct Foo
43 {
44 T t;
45 alias t this;
46 }
47 Foo foo;
48 static assert(is(typeof(hashOf(foo))));
49 }
50 // was fixed
51 testAlias!(int[]);
52 testAlias!(int*);
53 // was not affected
54 testAlias!int;
55 testAlias!(void delegate());
56 testAlias!(string[string]);
57 testAlias!(int[8]);
58 }
59
issues16654And16764()60 void issues16654And16764()
61 {
62 auto a = [1];
63 auto b = a.dup;
64 assert(hashOf(a) == hashOf(b));
65 }
66
67 /// Check hashOf dynamic array of scalars is usable in @safe code.
issue18918()68 void issue18918() nothrow pure @safe
69 {
70 const _ = (() @nogc => hashOf("abc"))();
71
72 static struct S { string array; }
73 auto s1 = S("abc");
74 auto s2 = S(s1.array.idup);
75 assert(hashOf(s1) == hashOf(s2));
76 enum e = hashOf(S("abc"));
77 assert(hashOf(s1) == e);
78 }
79
80 /// Check hashOf struct of scalar fields is usable in @safe code.
issue18925()81 void issue18925() @nogc nothrow pure @safe
82 {
83
84 static struct S { int a; int b; }
85 auto h = hashOf(S.init);
86 }
87
issue19005()88 void issue19005() @nogc nothrow pure @safe
89 {
90 enum Month : ubyte
91 {
92 jan = 1
93 }
94 static struct Date
95 {
96 short _year;
97 Month _month;
98 ubyte _day;
99 }
100 Date date;
101 auto hash = date.hashOf;
102 }
103
104 /// Accept SIMD vectors.
issue19204()105 void issue19204() @nogc nothrow pure @safe
106 {
107 version (D_SIMD)
108 {
109 static import simd = core.simd;
110 static if (is(simd.int4)) // __traits(isArithmetic)
111 {{
112 enum simd.int4 val = [1,2,3,4];
113 enum ctfeHash = hashOf(val);
114 simd.int4 rtVal = val;
115 auto rtHash = hashOf(rtVal);
116 assert(ctfeHash == rtHash);
117 }}
118 static if (is(simd.void16)) // non __traits(isArithmetic)
119 {{
120 auto h = hashOf(simd.void16.init);
121 }}
122 static if (is(simd.float4)) // __traits(isArithmetic) and __traits(isFloating)
123 {{
124 enum simd.float4 val = [1.1f, 2.2f, 3.3f, 4.4f];
125 enum ctfeHash = hashOf(val);
126 simd.float4 rtVal = val;
127 auto rtHash = hashOf(rtVal);
128 assert(ctfeHash == rtHash);
129 }}
130 }
131 }
132
133 /// hashOf associative array should infer nothrow
issue19262()134 void issue19262() nothrow
135 {
136 int[int] aa;
137 auto h = hashOf(aa);
138 h = hashOf(aa, h);
139 }
140
141 extern(C++) class Issue19282CppClass {}
142
143 /// test that hashOf doesn't crash for non-null C++ objects.
issue19282()144 void issue19282()
145 {
146 Issue19282CppClass c = new Issue19282CppClass();
147 size_t h = hashOf(c);
148 h = hashOf(c, h);
149 }
150
151 /// Ensure hashOf works for const struct that has non-const toHash & has all
152 /// fields bitwise-hashable. (Support might be removed in the future!)
issue19332()153 void issue19332()
154 {
155 static struct HasNonConstToHash
156 {
157 int a;
158 size_t toHash() { return a; }
159 }
160 const HasNonConstToHash val;
161 size_t h = hashOf(val);
162 h = hashOf!(const HasNonConstToHash)(val); // Ensure doesn't match more than one overload.
163 }
164
165 /// hashOf should not unnecessarily call a struct's fields' postblits & dtors in CTFE
issue19568()166 void issue19568()
167 {
168 static struct S1
169 {
170 @disable this(this);
171
172 ~this() @nogc nothrow
173 {
174 import core.stdc.stdio;
175 if (mptr) puts("impure");
176 }
177
178 size_t[2] pad;
179 void* mptr;
180 }
181
182 static struct S2
183 {
184 @disable this(this);
185
186 ~this() @nogc nothrow
187 {
188 import core.stdc.stdio;
189 if (fd != -1) puts("impure");
190 }
191
192 int fd = -1;
193 S1 s1;
194 }
195
196 static struct S3
197 {
198 private S2 s2;
199 }
200
201 S3 s3;
202 size_t h = ((ref S3 s3) pure => hashOf(s3))(s3);
203 }
204
205 /// Check core.internal.convert.toUbyte in CTFE for arrays works with
206 /// reference type elements and doesn't call postblits/dtors.
issue19582()207 void issue19582()
208 {
209 import core.internal.convert : toUbyte;
210 final static class C : Object {}
211 enum b1 = (() @nogc nothrow pure @safe { C[10] o; return toUbyte(o[])[0]; })();
212
213 static struct S
214 {
215 int x;
216 @disable this(this);
217 ~this() @nogc nothrow
218 {
219 import core.stdc.stdio : puts;
220 if (x) puts("impure");
221 }
222 }
223 enum b2 = () {
224 return ((const S[] a) @nogc nothrow pure @safe => toUbyte(a))(new S[10]);
225 }();
226 }
227
228 /// Check core.internal.hash.hashOf works with enums of non-scalar values
issue20034()229 void issue20034()
230 {
231 enum E
232 {
233 a = "foo"
234 }
235 // should compile
236 assert(hashOf(E.a, 1));
237 }
238
239 /// [REG 2.084] hashOf will fail to compile for some structs/unions that recursively contain shared enums
issue21642()240 void issue21642() @safe nothrow pure
241 {
242 enum C : char { _ = 1, }
243 union U { C c; void[0] _; }
244 shared union V { U u; }
245 cast(void) hashOf(V.init);
246 // Also test the underlying reason the above was failing.
247 import core.internal.convert : toUbyte;
248 shared C c;
249 assert(toUbyte(c) == [ubyte(1)]);
250 }
251
252 /// Accept enum type whose ultimate base type is a SIMD vector.
issue22024()253 void issue22024() @nogc nothrow pure @safe
254 {
255 static if (is(__vector(float[2])))
256 {
257 enum E2 : __vector(float[2]) { a = __vector(float[2]).init, }
258 enum F2 : E2 { a = E2.init, }
259 assert(hashOf(E2.init) == hashOf(F2.init));
260 assert(hashOf(E2.init, 1) == hashOf(F2.init, 1));
261 }
262 static if (is(__vector(float[4])))
263 {
264 enum E4 : __vector(float[4]) { a = __vector(float[4]).init, }
265 enum F4 : E4 { a = E4.init, }
266 assert(hashOf(E4.init) == hashOf(F4.init));
267 assert(hashOf(E4.init, 1) == hashOf(F4.init, 1));
268 }
269 }
270
271 /// hashOf(S) can segfault if S.toHash is forwarded via `alias this` to a
272 /// receiver which may be null.
issue22076()273 void issue22076()
274 {
275 static struct S0 { Object a; alias a this; }
276
277 static struct S1
278 {
279 S0 a;
280 inout(S0)* b() inout return nothrow { return &a; }
281 alias b this;
282 }
283
284 static struct S2
285 {
286 S0 a;
287 S1 b;
288 }
289
290 extern(C++) static class C0
291 {
292 int foo() { return 0; } // Need at least one function in vtable.
293 S0 a; alias a this;
294 }
295
296 extern(C++) static class C1
297 {
298 S1 a;
299 inout(S1)* b() inout nothrow { return &a; }
300 alias b this;
301 }
302
303 cast(void) hashOf(S0.init);
304 cast(void) hashOf(S0.init, 0);
305 cast(void) hashOf(S1.init);
306 cast(void) hashOf(S1.init, 0);
307 cast(void) hashOf(S2.init);
308 cast(void) hashOf(S2.init, 0);
309 auto c0 = new C0();
310 cast(void) hashOf(c0);
311 cast(void) hashOf(c0, 0);
312 auto c1 = new C1();
313 cast(void) hashOf(c1);
314 cast(void) hashOf(c1, 0);
315 }
316
317 /// Tests ensure TypeInfo_Array.getHash uses element hash functions instead
318 /// of hashing array data.
testTypeInfoArrayGetHash1()319 void testTypeInfoArrayGetHash1()
320 {
321 class C
322 {
323 int i;
324 this(in int i) { this.i = i; }
325 override hash_t toHash() { return 0; }
326 }
327 C[] a1 = [new C(11)], a2 = [new C(12)];
328 assert(typeid(C[]).getHash(&a1) == typeid(C[]).getHash(&a2));
329 }
330
331 /// ditto
testTypeInfoArrayGetHash2()332 void testTypeInfoArrayGetHash2()
333 {
334 struct S
335 {
336 int i;
337 hash_t toHash() const @safe nothrow { return 0; }
338 }
339 S[] a1 = [S(11)], a2 = [S(12)];
340 assert(typeid(S[]).getHash(&a1) == typeid(S[]).getHash(&a2));
341 }
342
343 /++
344 Use the new `core.internal.hash.hashOf` in all `TypeInfo.getHash` instead of
345 the `old rt.util.hash.hashOf`. Also make `typeid(T).getHash(&val)` get the
346 same result as `hashOf(val)`.
347 +/
pr2243()348 void pr2243()
349 {
350 static struct Foo
351 {
352 int a = 99;
353 float b = 4.0;
354 size_t toHash() const pure @safe nothrow
355 {
356 return a;
357 }
358 }
359
360 static struct Bar
361 {
362 char c = 'x';
363 int a = 99;
364 float b = 4.0;
365 void* d = null;
366 }
367
368 static struct Boom
369 {
370 char c = 'M';
371 int* a = null;
372 }
373
374 static struct Plain
375 {
376 int a = 1;
377 int b = 2;
378 }
379
380 interface IBoo
381 {
382 void boo();
383 }
384
385 static class Boo: IBoo
386 {
387 override void boo()
388 {
389 }
390
391 override size_t toHash()
392 {
393 return 1;
394 }
395 }
396
397 static struct Goo
398 {
399 size_t toHash() pure @safe nothrow
400 {
401 return 1;
402 }
403 }
404
405 enum Gun: long
406 {
407 A = 99,
408 B = 17
409 }
410
411 enum double dexpr = 3.14;
412 enum float fexpr = 2.71;
413 enum wstring wsexpr = "abcdef"w;
414 enum string csexpr = "abcdef";
415 enum int iexpr = 7;
416 enum long lexpr = 42;
417 enum int[2][3] saexpr = [[1, 2], [3, 4], [5, 6]];
418 enum int[] daexpr = [7,8,9];
419 enum Foo thsexpr = Foo();
420 enum Bar vsexpr = Bar();
421 enum int[int] aaexpr = [99:2, 12:6, 45:4];
422 enum Gun eexpr = Gun.A;
423 enum Foo[] staexpr = [Foo(), Foo(), Foo()];
424 enum Bar[] vsaexpr = [Bar(), Bar(), Bar()];
425 enum realexpr = 7.88;
426 enum nullexpr = null;
427 enum plstr = Plain();
428 enum plarrstr = [Plain(), Plain(), Plain()];
429 //No CTFE:
430 Boom rstructexpr = Boom();
431 Boom[] rstrarrexpr = [Boom(), Boom(), Boom()];
432 int delegate() dgexpr = (){return 78;};
433 void* ptrexpr = &dgexpr;
434
435
436 //CTFE hashes
437 enum h1 = dexpr.hashOf();
438 enum h2 = fexpr.hashOf();
439 enum h3 = wsexpr.hashOf();
440 enum h4 = csexpr.hashOf();
441 enum h5 = iexpr.hashOf();
442 enum h6 = lexpr.hashOf();
443 enum h7 = saexpr.hashOf();
444 enum h8 = daexpr.hashOf();
445 enum h9 = thsexpr.hashOf();
446 enum h10 = vsexpr.hashOf();
447 enum h11 = aaexpr.hashOf();
448 enum h12 = eexpr.hashOf();
449 enum h14 = hashOf(new Boo);
450 enum h15 = staexpr.hashOf();
451 enum h16 = hashOf([new Boo, new Boo, new Boo]);
452 enum h17 = hashOf([cast(IBoo)new Boo, cast(IBoo)new Boo, cast(IBoo)new Boo]);
453 enum h18 = hashOf(cast(IBoo)new Boo);
454 enum h19 = vsaexpr.hashOf();
455 enum h20 = hashOf(cast(Foo[3])staexpr);
456
457 //BUG: cannot cast [Boo(), Boo(), Boo()][0] to object.Object at compile time
458 auto h21 = hashOf(cast(Boo[3])[new Boo, new Boo, new Boo]);
459 auto h22 = hashOf(cast(IBoo[3])[cast(IBoo)new Boo, cast(IBoo)new Boo, cast(IBoo)new Boo]);
460 enum h23 = hashOf(cast(Bar[3])vsaexpr);
461
462 //NO CTFE (Compute, but don't check correctness):
463 auto h24 = rstructexpr.hashOf();
464 auto h25 = rstrarrexpr.hashOf();
465 auto h26 = dgexpr.hashOf();
466 auto h27 = ptrexpr.hashOf();
467
468 enum h28 = realexpr.hashOf();
469 enum h30 = nullexpr.hashOf();
470 enum h31 = plstr.hashOf();
471 enum h32 = plarrstr.hashOf();
472 enum h33 = hashOf(cast(Plain[3])plarrstr);
473
474 auto v1 = dexpr;
475 auto v2 = fexpr;
476 auto v3 = wsexpr;
477 auto v4 = csexpr;
478 auto v5 = iexpr;
479 auto v6 = lexpr;
480 auto v7 = saexpr;
481 auto v8 = daexpr;
482 auto v9 = thsexpr;
483 auto v10 = vsexpr;
484 auto v11 = aaexpr;
485 auto v12 = eexpr;
486 auto v14 = new Boo;
487 auto v15 = staexpr;
488 auto v16 = [new Boo, new Boo, new Boo];
489 auto v17 = [cast(IBoo)new Boo, cast(IBoo)new Boo, cast(IBoo)new Boo];
490 auto v18 = cast(IBoo)new Boo;
491 auto v19 = vsaexpr;
492 auto v20 = cast(Foo[3])staexpr;
493 auto v21 = cast(Boo[3])[new Boo, new Boo, new Boo];
494 auto v22 = cast(IBoo[3])[cast(IBoo)new Boo, cast(IBoo)new Boo, cast(IBoo)new Boo];
495 auto v23 = cast(Bar[3])vsaexpr;
496 auto v30 = null;
497 auto v31 = plstr;
498 auto v32 = plarrstr;
499 auto v33 = cast(Plain[3])plarrstr;
500
501 //NO CTFE:
502 auto v24 = rstructexpr;
503 auto v25 = rstrarrexpr;
504 auto v26 = dgexpr;
505 auto v27 = ptrexpr;
506 auto v28 = realexpr;
507
508 //runtime hashes
509 auto rth1 = hashOf(v1);
510 auto rth2 = hashOf(v2);
511 auto rth3 = hashOf(v3);
512 auto rth4 = hashOf(v4);
513 auto rth5 = hashOf(v5);
514 auto rth6 = hashOf(v6);
515 auto rth7 = hashOf(v7);
516 auto rth8 = hashOf(v8);
517 auto rth9 = hashOf(v9);
518 auto rth10 = hashOf(v10);
519 auto rth11 = hashOf(v11);
520 auto rth12 = hashOf(v12);
521 auto rth14 = hashOf(v14);
522 auto rth15 = hashOf(v15);
523 auto rth16 = hashOf(v16);
524 auto rth17 = hashOf(v17);
525 auto rth18 = hashOf(v18);
526 auto rth19 = hashOf(v19);
527 auto rth20 = hashOf(v20);
528 auto rth21 = hashOf(v21);
529 auto rth22 = hashOf(v22);
530 auto rth23 = hashOf(v23);
531 auto rth30 = hashOf(v30);
532 //NO CTFE:
533 auto rth24 = hashOf(v24);
534 auto rth25 = hashOf(v25);
535 auto rth26 = hashOf(v26);
536 auto rth27 = hashOf(v27);
537 auto rth28 = hashOf(v28);
538
539 auto rth31 = hashOf(v31);
540 auto rth32 = hashOf(v32);
541 auto rth33 = hashOf(v33);
542
543 assert(h1 == rth1);
544 assert(h2 == rth2);
545 assert(h3 == rth3);
546 assert(h4 == rth4);
547 assert(h5 == rth5);
548 assert(h6 == rth6);
549 assert(h7 == rth7);
550 assert(h8 == rth8);
551 assert(h9 == rth9);
552 assert(h10 == rth10);
553 assert(h11 == rth11);
554 assert(h12 == rth12);
555 assert(h14 == rth14);
556 assert(h15 == rth15);
557 assert(h16 == rth16);
558 assert(h17 == rth17);
559 assert(h18 == rth18);
560 assert(h19 == rth19);
561 assert(h20 == rth20);
562 assert(h21 == rth21);
563 assert(h22 == rth22);
564 assert(h23 == rth23);
565 /*assert(h24 == rth24);
566 assert(h25 == rth25);
567 assert(h26 == rth26);
568 assert(h27 == rth27);
569 assert(h28 == rth28);*/
570 assert(h30 == rth30);
571 assert(h31 == rth31);
572 assert(h32 == rth32);
573 assert(h33 == rth33);
574
575 // https://issues.dlang.org/show_bug.cgi?id=18932
576 assert(hashOf(null, 0) != hashOf(null, 123456789));
577
578 static size_t tiHashOf(T)(T var)
579 {
580 return typeid(T).getHash(&var);
581 }
582
583 auto tih1 = tiHashOf(v1);
584 auto tih2 = tiHashOf(v2);
585 auto tih3 = tiHashOf(v3);
586 auto tih4 = tiHashOf(v4);
587 auto tih5 = tiHashOf(v5);
588 auto tih6 = tiHashOf(v6);
589 auto tih7 = tiHashOf(v7);
590 auto tih8 = tiHashOf(v8);
591 auto tih9 = tiHashOf(v9);
592 auto tih10 = tiHashOf(v10);
593 auto tih11 = tiHashOf(v11);
594 auto tih12 = tiHashOf(v12);
595 auto tih14 = tiHashOf(v14);
596 auto tih15 = tiHashOf(v15);
597 auto tih16 = tiHashOf(v16);
598 auto tih17 = tiHashOf(v17);
599 auto tih18 = tiHashOf(v18);
600 auto tih19 = tiHashOf(v19);
601 auto tih20 = tiHashOf(v20);
602 auto tih21 = tiHashOf(v21);
603 auto tih22 = tiHashOf(v22);
604 auto tih23 = tiHashOf(v23);
605 auto tih24 = tiHashOf(v24);
606 auto tih25 = tiHashOf(v25);
607 auto tih26 = tiHashOf(v26);
608 auto tih27 = tiHashOf(v27);
609 auto tih28 = tiHashOf(v28);
610 auto tih30 = tiHashOf(v30);
611 auto tih31 = tiHashOf(v31);
612 auto tih32 = tiHashOf(v32);
613 auto tih33 = tiHashOf(v33);
614
615 assert(tih1 == rth1);
616 assert(tih2 == rth2);
617 assert(tih3 == rth3);
618 assert(tih4 == rth4);
619 assert(tih5 == rth5);
620 assert(tih6 == rth6);
621 assert(tih7 == rth7);
622 assert(tih8 == rth8);
623 assert(tih9 == rth9);
624 //assert(tih10 == rth10); // need compiler-generated __xtoHash changes
625 assert(tih11 == rth11);
626 assert(tih12 == rth12);
627 assert(tih14 == rth14);
628 assert(tih15 == rth15);
629 assert(tih16 == rth16);
630 assert(tih17 == rth17);
631 assert(tih18 == rth18);
632 //assert(tih19 == rth19); // need compiler-generated __xtoHash changes
633 assert(tih20 == rth20);
634 assert(tih21 == rth21);
635 assert(tih22 == rth22);
636 //assert(tih23 == rth23); // need compiler-generated __xtoHash changes
637 //assert(tih24 == rth24);
638 //assert(tih25 == rth25);
639 assert(tih26 == rth26);
640 assert(tih27 == rth27);
641 assert(tih28 == rth28);
642 assert(tih30 == rth30);
643 assert(tih31 == rth31);
644 assert(tih32 == rth32);
645 assert(tih33 == rth33);
646 }
647