1 /**
2     Implementation of unique pointer `UniquePtr` (alias to `btl.autoptr.rc_ptr.RcPtr` with immutable control block).
3 
4     License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
5     Authors:   Adam Búš
6 */
7 module btl.autoptr.unique_ptr;
8 
9 import btl.internal.allocator;
10 import btl.internal.traits;
11 
12 static import btl.autoptr.rc_ptr;
13 import btl.autoptr.common;
14 
15 
16 
17 /**
18     Alias to `btl.autoptr.rc_ptr.dynCast`.
19 */
20 public alias dynCast = btl.autoptr.rc_ptr.dynCast;
21 
22 
23 
24 /**
25     Alias to `btl.autoptr.rc_ptr.dynCastMove`.
26 */
27 public alias dynCastMove = btl.autoptr.rc_ptr.dynCastMove;
28 
29 
30 
31 /**
32     Alias to `btl.autoptr.rc_ptr.first`.
33 */
34 public alias first = btl.autoptr.rc_ptr.first;
35 
36 
37 
38 /**
39     Alias to `btl.autoptr.rc_ptr.share`.
40 */
41 public alias share = btl.autoptr.rc_ptr.share;
42 
43 
44 
45 /**
46     Check if type `T` is `UniquePtr`.
47 */
48 public template isUniquePtr(T){
49     import std.traits : isInstanceOf;
50 
51     static if(isRcPtr!T)
52         enum bool isUniquePtr = is(T.ControlType == immutable); //is(GetControlType!T == immutable);
53     else
54         enum bool isUniquePtr = false;
55 }
56 
57 
58 
59 /**
60     `UniquePtr` is a smart pointer that owns and manages object through a pointer and disposes of that object when the `UniquePtr` goes out of scope.
61 
62     `UniquePtr` is alias to `btl.autoptr.rc_ptr.RcPtr` with immutable `_ControlType`.
63 
64     The object is destroyed and its memory deallocated when either of the following happens:
65 
66         1. the managing `UniquePtr` object is destroyed
67 
68         2. the managing `UniquePtr` object is assigned another pointer via various methods like `opAssign` and `store`.
69 
70     The object is destroyed using delete-expression or a custom deleter that is supplied to `UniquePtr` during construction.
71 
72     A `UniquePtr` may alternatively own no object, in which case it is called empty.
73 
74     Template parameters:
75 
76         `_Type` type of managed object
77 
78         `_DestructorType` function pointer with attributes of destructor, to get attributes of destructor from type use `btl.autoptr.common.DestructorType!T`. Destructor of type `_Type` must be compatible with `_DestructorType`
79 
80         `_ControlType` represent type of counter, must by of type immutable `btl.autoptr.common.ControlBlock`.
81 */
82 public template UniquePtr(
83     _Type,
84     _DestructorType = DestructorType!_Type,
85     _ControlType = immutable(UniqueControlBlock),
86 )
87 if(isControlBlock!_ControlType && isDestructorType!_DestructorType){
88     static assert(is(_ControlType == immutable));
89 
90     alias UniquePtr = btl.autoptr.rc_ptr.RcPtr!(_Type, _DestructorType, _ControlType);
91 }
92 
93 /// ditto
94 public template UniquePtr(
95     _Type,
96     _ControlType,
97     _DestructorType = DestructorType!_Type
98 )
99 if(isControlBlock!_ControlType && isDestructorType!_DestructorType){
100     static assert(is(_ControlType == immutable));
101 
102     alias UniquePtr = btl.autoptr.rc_ptr.RcPtr!(_Type, _DestructorType, _ControlType);
103 }
104 
105 ///
106 unittest{
107     static class Foo{
108         int i;
109 
110         this(int i)pure nothrow @safe @nogc{
111             this.i = i;
112         }
113     }
114 
115     static class Bar : Foo{
116         double d;
117 
118         this(int i, double d)pure nothrow @safe @nogc{
119             super(i);
120             this.d = d;
121         }
122     }
123 
124     static class Zee : Bar{
125         bool b;
126 
127         this(int i, double d, bool b)pure nothrow @safe @nogc{
128             super(i, d);
129             this.b = b;
130         }
131 
132         ~this()nothrow @system{
133         }
134     }
135 
136     import core.lifetime : move;
137     ///simple:
138     {
139         UniquePtr!long a = UniquePtr!long.make(42);
140         UniquePtr!(const long) b = move(a);
141         assert(a == null);
142 
143         assert(*b == 42);
144         assert(b.get == 42);
145     }
146 
147     ///polymorphism:
148     {
149         ///create UniquePtr
150         UniquePtr!Foo foo = UniquePtr!Bar.make(42, 3.14);
151         UniquePtr!Zee zee = UniquePtr!Zee.make(42, 3.14, false);
152 
153         ///dynamic cast:
154         UniquePtr!Bar bar = dynCastMove!Bar(foo);
155         assert(foo == null);
156         assert(bar != null);
157 
158         ///this doesnt work because Foo destructor attributes are more restrictive then Zee's:
159         //UniquePtr!Foo x = move(zee);
160 
161         ///this does work:
162         UniquePtr!(Foo, DestructorType!(Foo, Zee)) x = move(zee);
163         assert(zee == null);
164     }
165 
166 
167     ///multi threading:
168     {
169         ///create SharedPtr with atomic ref counting
170         UniquePtr!(shared Foo) foo = UniquePtr!(shared Bar).make(42, 3.14);
171 
172         ///this doesnt work:
173         //foo.get.i += 1;
174 
175         import core.atomic : atomicFetchAdd;
176         atomicFetchAdd(foo.get.i, 1);
177         assert(foo.get.i == 43);
178 
179 
180         ///creating `shared(UniquePtr)`:
181         shared UniquePtr!(shared Bar) bar = share(dynCastMove!Bar(foo));
182 
183         ///`shared(UniquePtr)` is lock free.
184         static assert(typeof(bar).isLockFree == true);
185 
186         ///multi thread operations (`store`, `exchange`):
187         UniquePtr!(shared Bar) bar2 = bar.exchange(null);
188     }
189 
190     ///dynamic array:
191     {
192         import std.algorithm : all, equal;
193 
194         UniquePtr!(long[]) a = UniquePtr!(long[]).make(10, -1);
195         assert(a.length == 10);
196         assert(a.get.length == 10);
197         assert(a.get.all!(x => x == -1));
198 
199         for(int i = 0; i < a.length; ++i){
200             a.get[i] = i;
201         }
202         assert(a.get[] == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
203     }
204 }
205 
206 //old
207 pure nothrow @nogc unittest{
208 
209     static class Foo{
210         int i;
211 
212         this(int i)pure nothrow @safe @nogc{
213             this.i = i;
214         }
215     }
216 
217     static class Bar : Foo{
218         double d;
219 
220         this(int i, double d)pure nothrow @safe @nogc{
221             super(i);
222             this.d = d;
223         }
224     }
225 
226     //implicit qualifier cast
227     {
228         UniquePtr!(const Foo) foo =  UniquePtr!Foo.make(42);
229         assert(foo.get.i == 42);
230 
231         import core.lifetime : move;
232         const UniquePtr!Foo foo2 = foo.move;
233         assert(foo2.get.i == 42);
234 
235     }
236 
237     //polymorphic classes:
238     {
239         UniquePtr!Foo foo = UniquePtr!Bar.make(42, 3.14);
240         assert(foo != null);
241         assert(foo.get.i == 42);
242 
243         //dynamic cast:
244         {
245             UniquePtr!Bar bar = dynCastMove!Bar(foo);
246             assert(foo == null);
247             assert(bar != null);
248 
249             assert(bar.get.i == 42);
250             assert(bar.get.d == 3.14);
251         }
252 
253     }
254 
255     //dynamic array
256     {
257         import std.algorithm : all;
258 
259         {
260             auto arr = UniquePtr!(long[]).make(10, -1);
261 
262             assert(arr.length == 10);
263             assert(arr.get.all!(x => x == -1));
264         }
265 
266         {
267             auto arr = UniquePtr!(long[]).make(8);
268             assert(arr.length == 8);
269             assert(arr.get.all!(x => x == long.init));
270         }
271     }
272 
273     //static array
274     {
275         import std.algorithm : all;
276 
277         {
278             auto arr = UniquePtr!(long[4]).make(-1);
279             assert(arr.get[].all!(x => x == -1));
280 
281         }
282 
283         {
284             long[4] tmp = [0, 1, 2, 3];
285             auto arr = UniquePtr!(long[4]).make(tmp);
286             assert(arr.get[] == tmp[]);
287         }
288     }
289 
290 }
291 
292 ///
293 pure nothrow @safe @nogc unittest{
294     //make UniquePtr object
295     static struct Foo{
296         int i;
297 
298         this(int i)pure nothrow @safe @nogc{
299             this.i = i;
300         }
301     }
302 
303     {
304         auto foo = UniquePtr!Foo.make(42);
305         auto foo2 = UniquePtr!Foo.make!Mallocator(42);  //explicit stateless allocator
306     }
307 
308     {
309         auto arr = UniquePtr!(long[]).make(10); //dynamic array with length 10
310         assert(arr.length == 10);
311     }
312 }
313 
314 ///
315 nothrow unittest{
316     //alloc UniquePtr object
317     import std.experimental.allocator : make, dispose, allocatorObject;
318 
319     auto allocator = allocatorObject(Mallocator.instance);
320 
321     {
322         auto x = UniquePtr!(long).alloc(allocator, 42);
323     }
324 
325     {
326         auto arr = UniquePtr!(long[]).alloc(allocator, 10); //dynamic array with length 10
327         assert(arr.length == 10);
328     }
329 
330 }
331 
332 
333 
334 
335 
336 // make:
337 pure nothrow @safe @nogc unittest{
338 
339     enum bool supportGC = true;
340 
341     //
342     {
343         auto s = UniquePtr!long.make(42);
344     }
345 
346     {
347         auto s = UniquePtr!long.make!(DefaultAllocator, supportGC)(42);
348     }
349 
350     {
351         auto s = UniquePtr!(long, immutable(SharedControlBlock)).make!(DefaultAllocator, supportGC)(42);
352     }
353 
354     // dynamic array:
355     {
356         auto s = UniquePtr!(long[]).make(10, 42);
357         assert(s.length == 10);
358     }
359 
360     {
361         auto s = UniquePtr!(long[]).make!(DefaultAllocator, supportGC)(10, 42);
362         assert(s.length == 10);
363     }
364 
365     {
366         auto s = UniquePtr!(long[], immutable(SharedControlBlock)).make!(DefaultAllocator, supportGC)(10, 42);
367         assert(s.length == 10);
368     }
369 }
370 
371 // alloc:
372 nothrow unittest{
373     import std.experimental.allocator : allocatorObject;
374 
375     auto a = allocatorObject(Mallocator.instance);
376     enum bool supportGC = true;
377 
378     //
379     {
380         auto s = UniquePtr!long.alloc(a, 42);
381     }
382 
383     {
384         auto s = UniquePtr!long.alloc!supportGC(a, 42);
385     }
386 
387     {
388         auto s = UniquePtr!(long, immutable(SharedControlBlock)).alloc!supportGC(a, 42);
389     }
390 
391     // dynamic array:
392     {
393         auto s = UniquePtr!(long[]).alloc(a, 10, 42);
394         assert(s.length == 10);
395     }
396 
397     {
398         auto s = UniquePtr!(long[]).alloc!supportGC(a, 10, 42);
399         assert(s.length == 10);
400     }
401 
402     {
403         auto s = UniquePtr!(long[], immutable(SharedControlBlock)).alloc!supportGC(a, 10, 42);
404         assert(s.length == 10);
405     }
406 }
407 
408 ///
409 nothrow @nogc unittest{
410     {
411         auto x = UniquePtr!(shared long).make(123);
412 
413         import core.lifetime : move;
414         shared s = share(x.move);
415         assert(x == null);
416 
417         auto y = s.exchange(null);
418         assert(*y == 123);
419     }
420 
421     {
422         auto x = UniquePtr!(long).make(123);
423 
424         ///error `shared UniquePtr` need shared `ControlType` and shared `ElementType`.
425         //shared s = share(x);
426 
427     }
428 }
429 
430 //
431 pure nothrow @nogc unittest{
432     import core.lifetime : move;
433 
434     {
435         auto x = UniquePtr!(long[]).make(10, -1);
436         assert(x.length == 10);
437 
438         auto y = first(x.move);
439         static assert(is(typeof(y) == UniquePtr!long));
440         assert(*y == -1);
441     }
442 
443     {
444         auto x = UniquePtr!(long[10]).make(-1);
445         assert(x.get.length == 10);
446 
447         auto y = first(x.move);
448         static assert(is(typeof(y) == UniquePtr!long));
449         assert(*y == -1);
450     }
451 }
452 
453 //
454 pure @safe nothrow @nogc unittest{
455     static class Foo{
456         int i;
457 
458         this(int i)pure nothrow @safe @nogc{
459             this.i = i;
460         }
461     }
462 
463     static class Bar : Foo{
464         double d;
465 
466         this(int i, double d)pure nothrow @safe @nogc{
467             super(i);
468             this.d = d;
469         }
470     }
471 
472     static class Zee{
473     }
474 
475     {
476         UniquePtr!(const Foo) foo = UniquePtr!Bar.make(42, 3.14);
477         //assert(foo.get.i == 42);
478 
479         auto bar = dynCastMove!Bar(foo);
480         assert(bar != null);
481         assert(foo == null);
482         //assert(bar.get.d == 3.14);
483         static assert(is(typeof(bar) == UniquePtr!(const Bar)));
484 
485         auto zee = dynCastMove!Zee(bar);
486         assert(zee == null);
487         assert(bar != null);
488         static assert(is(typeof(zee) == UniquePtr!(const Zee)));
489     }
490 }
491 
492 
493 //
494 unittest{
495     static class Foo{
496         int i;
497 
498         this(int i)pure nothrow @safe @nogc{
499             this.i = i;
500         }
501     }
502 
503     static class Bar : Foo{
504         double d;
505 
506         this(int i, double d)pure nothrow @safe @nogc{
507             super(i);
508             this.d = d;
509         }
510     }
511 
512     static class Zee{
513     }
514 
515     {
516         import core.lifetime : move;
517 
518         UniquePtr!(const Foo) foo = UniquePtr!Bar.make(42, 3.14);
519         assert(foo.get.i == 42);
520 
521         auto bar = dynCast!Bar(foo.move);
522         assert(bar != null);
523         assert(foo == null);
524         assert(bar.get.d == 3.14);
525         static assert(is(typeof(bar) == UniquePtr!(const Bar)));
526 
527         auto zee = dynCast!Zee(bar.move);
528         assert(zee == null);
529         assert(bar == null);
530         static assert(is(typeof(zee) == UniquePtr!(const Zee)));
531     }
532 }
533 
534 
535 version(unittest){
536 
537 
538     //this null
539     pure nothrow @nogc unittest{
540         UniquePtr!long x = null;
541 
542         assert(x == null);
543         assert(x == UniquePtr!long.init);
544     }
545 
546     //this rhs
547     pure nothrow @nogc unittest{
548         //TODO
549     }
550 
551 
552     //opAssign null
553     pure nothrow @nogc unittest{
554 
555         {
556             UniquePtr!long x = UniquePtr!long.make(1);
557 
558             assert(x != null);
559             assert(*x == 1);
560             x = null;
561             assert(x == null);
562         }
563 
564         {
565             UniquePtr!(shared long) x = UniquePtr!(shared long).make(1);
566 
567             assert(x != null);
568             assert(*x == 1);
569             x = null;
570             assert(x == null);
571         }
572     }
573 
574     //opAssign UniquePtr
575     pure nothrow @nogc unittest{
576 
577         import core.lifetime : move;
578         {
579             UniquePtr!long px1 = UniquePtr!long.make(1);
580             UniquePtr!long px2 = UniquePtr!long.make(2);
581 
582             px1 = move(px2);
583             assert(px2 == null);
584             assert(px1 != null);
585             assert(*px1 == 2);
586         }
587 
588 
589         {
590             UniquePtr!long px = UniquePtr!long.make(1);
591             UniquePtr!(const long) pcx = UniquePtr!long.make(2);
592 
593             pcx = move(px);
594             assert(px == null);
595             assert(pcx != null);
596             assert(*pcx == 1);
597 
598         }
599     }
600 
601     //store
602     nothrow @nogc unittest{
603         //null store:
604         {
605             shared x = UniquePtr!(shared long).make(123);
606             //*x == 123
607 
608             x.store(null);
609             //x is null
610         }
611 
612         //rvalue store:
613         {
614             shared x = UniquePtr!(shared long).make(123);
615             //*x == 123
616 
617             x.store(UniquePtr!(shared long).make(42));
618             //*x == 42
619 
620             auto tmp = x.exchange(null);
621             //x is null
622             assert(tmp.get == 42);
623         }
624     }
625 
626     //exchange
627     pure nothrow @nogc unittest{
628         import core.lifetime : move;
629 
630         {
631             shared UniquePtr!(shared long) x = UniquePtr!(shared long).make(123);
632             UniquePtr!(shared long) y = UniquePtr!(shared long).make(42);
633 
634             auto z = x.exchange(y.move);
635             assert(y == null);
636             assert(*z == 123);
637 
638             auto tmp = x.exchange(null);
639             assert(*tmp == 42);
640         }
641 
642         //swap:
643         {
644             shared UniquePtr!(shared long) x = UniquePtr!(shared long).make(123);
645             UniquePtr!(shared long) y = UniquePtr!(shared long).make(42);
646 
647             y = x.exchange(y.move);
648             assert(*y == 123);
649 
650             auto tmp = x.exchange(null);
651             assert(*tmp == 42);
652         }
653     }
654 
655     //make
656     pure nothrow @nogc unittest{
657 
658         {
659             UniquePtr!long a = UniquePtr!long.make();
660             assert(a.get == 0);
661 
662             UniquePtr!(const long) b = UniquePtr!long.make(2);
663             assert(b.get == 2);
664         }
665 
666         {
667             static struct Struct{
668                 int i = 7;
669 
670                 this(int i)pure nothrow @safe @nogc{
671                     this.i = i;
672                 }
673             }
674 
675             UniquePtr!Struct s1 = UniquePtr!Struct.make();
676             assert(s1.get.i == 7);
677 
678             UniquePtr!Struct s2 = UniquePtr!Struct.make(123);
679             assert(s2.get.i == 123);
680         }
681     }
682 
683     //make dynamic array
684     pure nothrow @nogc unittest{
685         auto arr = UniquePtr!(long[]).make(6, -1);
686         assert(arr.length == 6);
687         assert(arr.get.length == 6);
688 
689         import std.algorithm : all;
690         assert(arr.get.all!(x => x == -1));
691 
692         for(int i = 0; i < 6; ++i)
693             arr.get[i] = i;
694 
695         assert(arr.get == [0, 1, 2, 3, 4, 5]);
696     }
697 
698     //alloc
699     nothrow unittest{
700         import std.experimental.allocator : allocatorObject;
701         auto a = allocatorObject(Mallocator.instance);
702         {
703             auto x = UniquePtr!long.alloc(a);
704             assert(x.get == 0);
705 
706             auto y = UniquePtr!(const long).alloc(a, 2);
707             assert(y.get == 2);
708         }
709 
710         {
711             static struct Struct{
712                 int i = 7;
713 
714                 this(int i)pure nothrow @safe @nogc{
715                     this.i = i;
716                 }
717             }
718 
719             auto s1 = UniquePtr!Struct.alloc(a);
720             assert(s1.get.i == 7);
721 
722             auto s2 = UniquePtr!Struct.alloc(a, 123);
723             assert(s2.get.i == 123);
724         }
725     }
726 
727     //alloc dynamic array
728     nothrow unittest{
729         import std.experimental.allocator : allocatorObject;
730         auto a = allocatorObject(Mallocator.instance);
731         {
732             auto x = UniquePtr!long.alloc(a);
733             assert(x.get == 0);
734 
735             auto y = UniquePtr!(const long).alloc(a, 2);
736             assert(y.get == 2);
737         }
738 
739         {
740             static struct Struct{
741                 int i = 7;
742 
743                 this(int i)pure nothrow @safe @nogc{
744                     this.i = i;
745                 }
746             }
747 
748             auto s1 = UniquePtr!Struct.alloc(a);
749             assert(s1.get.i == 7);
750 
751             auto s2 = UniquePtr!Struct.alloc(a, 123);
752             assert(s2.get.i == 123);
753         }
754     }
755 
756     //proxySwap
757     pure nothrow @nogc unittest{
758         {
759             UniquePtr!long a = UniquePtr!long.make(1);
760             UniquePtr!long b = UniquePtr!long.make(2);
761             a.proxySwap(b);
762             assert(*a == 2);
763             assert(*b == 1);
764             import std.algorithm : swap;
765             swap(a, b);
766             assert(*a == 1);
767             assert(*b == 2);
768         }
769     }
770 
771     //opUnary : '*'
772     pure nothrow @nogc unittest{
773         import core.lifetime : move;
774 
775         UniquePtr!long x = UniquePtr!long.make(123);
776         assert(*x == 123);
777         (*x = 321);
778         assert(*x == 321);
779         const y = move(x);
780         assert(*y == 321);
781         assert(x == null);
782         static assert(is(typeof(*y) == const long));
783     }
784 
785     //get
786     pure nothrow @nogc unittest{
787         import core.lifetime : move;
788 
789         UniquePtr!long x = UniquePtr!long.make(123);
790         assert(x.get == 123);
791         x.get = 321;
792         assert(x.get == 321);
793         const y = move(x);
794         assert(y.get == 321);
795         assert(x == null);
796         static assert(is(typeof(y.get) == const long));
797     }
798 
799     //element
800     pure nothrow @nogc unittest{
801         import core.lifetime : move;
802 
803         UniquePtr!long x = UniquePtr!long.make(123);
804         assert(*x.element == 123);
805         x.get = 321;
806         assert(*x.element == 321);
807         const y = move(x);
808         assert(*y.element == 321);
809         assert(x == null);
810         static assert(is(typeof(y.element) == const(long)*));
811     }
812 
813     //length
814     pure nothrow @nogc unittest{
815         auto x = UniquePtr!(int[]).make(10, -1);
816         assert(x.length == 10);
817         assert(x.get.length == 10);
818 
819         import std.algorithm : all;
820         assert(x.get.all!(i => i == -1));
821     }
822 
823     //opCast : bool
824     /+TODO
825     pure nothrow @nogc unittest{
826 
827         UniquePtr!long x = UniquePtr!long.make(123);
828         assert(cast(bool)x);    //explicit cast
829         assert(x);              //implicit cast
830         x = null;
831         assert(!cast(bool)x);   //explicit cast
832         assert(!x);             //implicit cast
833     }
834     +/
835 
836 
837     //opEquals
838     pure nothrow @nogc unittest{
839 
840         {
841             UniquePtr!long x = UniquePtr!long.make(0);
842             assert(x != null);
843             x = null;
844             assert(x == null);
845         }
846 
847         {
848             UniquePtr!long x = UniquePtr!long.make(123);
849             UniquePtr!long y = UniquePtr!long.make(123);
850             assert(x == x);
851             assert(y == y);
852             assert(x != y);
853         }
854 
855         {
856             UniquePtr!long x;
857             UniquePtr!(const long) y;
858             assert(x == x);
859             assert(y == y);
860             assert(x == y);
861         }
862 
863         {
864             UniquePtr!long x = UniquePtr!long.make(123);
865             UniquePtr!long y = UniquePtr!long.make(123);
866             assert(x == x.element);
867             assert(y.element == y);
868             assert(x != y.element);
869         }
870     }
871 
872     //opCmp
873     pure nothrow @nogc unittest{
874         {
875             const a = UniquePtr!long.make(42);
876             const b = UniquePtr!long.make(123);
877             const n = UniquePtr!long.init;
878 
879             assert((a < b) == !(a >= b));
880             assert((a > b) == !(a <= b));
881 
882             assert(a > n);
883             assert(n < a);
884         }
885 
886         {
887             const a = UniquePtr!long.make(42);
888             const b = UniquePtr!long.make(123);
889 
890             assert((a < b.element) == !(a.element >= b));
891             assert((a > b.element) == !(a.element <= b));
892         }
893     }
894 
895     //toHash
896     pure nothrow @nogc unittest{
897         import core.lifetime : move;
898         {
899             UniquePtr!long x = UniquePtr!long.make(123);
900             UniquePtr!long y = UniquePtr!long.make(123);
901             assert(x.toHash == x.toHash);
902             assert(y.toHash == y.toHash);
903             assert(x.toHash != y.toHash);
904 
905             const x_hash = x.toHash;
906             UniquePtr!(const long) z = move(x);
907             assert(x_hash == z.toHash);
908         }
909         {
910             UniquePtr!long x;
911             UniquePtr!(const long) y;
912             assert(x.toHash == x.toHash);
913             assert(y.toHash == y.toHash);
914             assert(x.toHash == y.toHash);
915         }
916     }
917 
918 
919 }