@@ -449,6 +449,196 @@ impl<T: Copy> WriteCloneIntoRaw for T {
449
449
}
450
450
}
451
451
452
+ #[ cfg( all( not( no_global_oom_handling) , not( test) ) ) ]
453
+ use core:: error:: Error ;
454
+
455
+ /// Trait for handling alloc errors for allocators which
456
+ /// panic or abort instead of returning errors.
457
+ #[ unstable( feature = "allocator_api" , issue = "32838" ) ]
458
+ #[ cfg( all( not( no_global_oom_handling) , not( test) ) ) ]
459
+ #[ rustc_specialization_trait]
460
+ pub trait HandleAllocError : Error {
461
+ /// Globally handle this allocation error
462
+ fn handle_alloc_error ( self ) -> !;
463
+ }
464
+
465
+ /// Error handling mode to use when the user of the type wants to ignore
466
+ /// allocation failures, treating them as a fatal error. Functions
467
+ /// performing allocation will return values directly.
468
+ #[ derive( Debug ) ]
469
+ #[ unstable( feature = "allocator_api" , issue = "32838" ) ]
470
+ #[ cfg( all( not( no_global_oom_handling) , not( test) ) ) ]
471
+ pub struct Fatal ;
472
+
473
+ #[ unstable( feature = "alloc_internals" , issue = "none" ) ]
474
+ #[ cfg( all( not( no_global_oom_handling) , not( test) ) ) ]
475
+ impl error_handling_sealed:: Sealed for Fatal { }
476
+
477
+ #[ unstable( feature = "allocator_api" , issue = "32838" ) ]
478
+ #[ cfg( all( not( no_global_oom_handling) , not( test) ) ) ]
479
+ impl ErrorHandling for Fatal {
480
+ type Result < T , E : Error > = T ;
481
+
482
+ fn map_result < T , E : Error > ( result : Result < T , E > ) -> Self :: Result < T , E > {
483
+ /// Hack around lack of `cfg(no_global_oom_handling)` in core.
484
+ ///
485
+ /// Using post-monomorphization errors and specialization,
486
+ /// we can enforce that any error used with `Fatal` implements
487
+ /// `HandleAllocError`, without requiring that all errors used
488
+ /// with fallible allocation implement it. This also allows
489
+ /// for `HandleAllocError` to live with the rest of the
490
+ /// global allocation handling in the `alloc` crate.
491
+ trait HandleAllocErrorInternal {
492
+ fn handle_alloc_error_internal ( self ) -> !;
493
+ }
494
+ impl < E : Error > HandleAllocErrorInternal for E {
495
+ default fn handle_alloc_error_internal ( self ) -> ! {
496
+ const {
497
+ panic ! (
498
+ "user must implement `HandleAllocError` for any error type used with the `Fatal` kind of `ErrorHandling`"
499
+ )
500
+ }
501
+ }
502
+ }
503
+ impl < E : HandleAllocError > HandleAllocErrorInternal for E {
504
+ fn handle_alloc_error_internal ( self ) -> ! {
505
+ self . handle_alloc_error ( )
506
+ }
507
+ }
508
+
509
+ result. unwrap_or_else ( |e| e. handle_alloc_error_internal ( ) )
510
+ }
511
+ }
512
+
513
+ /// Wrapper around an existing allocator allowing one to
514
+ /// use a fallible allocator as an infallible one.
515
+ #[ unstable( feature = "allocator_api" , issue = "32838" ) ]
516
+ #[ cfg( all( not( no_global_oom_handling) , not( test) ) ) ]
517
+ #[ derive( Debug ) ]
518
+ pub struct FatalAdapter < A : Allocator < ErrorHandling = Fallible > > ( pub A ) ;
519
+
520
+ #[ unstable( feature = "allocator_api" , issue = "32838" ) ]
521
+ #[ cfg( all( not( no_global_oom_handling) , not( test) ) ) ]
522
+ unsafe impl < A : Allocator < ErrorHandling = Fallible > > Allocator for FatalAdapter < A > {
523
+ fn allocate ( & self , layout : Layout ) -> Result < core:: ptr:: NonNull < [ u8 ] > , AllocError > {
524
+ self . 0 . allocate ( layout)
525
+ }
526
+
527
+ fn allocate_zeroed ( & self , layout : Layout ) -> Result < core:: ptr:: NonNull < [ u8 ] > , AllocError > {
528
+ self . 0 . allocate_zeroed ( layout)
529
+ }
530
+
531
+ unsafe fn deallocate ( & self , ptr : core:: ptr:: NonNull < u8 > , layout : Layout ) {
532
+ // SAFETY: the safety contract must be upheld by the caller
533
+ unsafe { self . 0 . deallocate ( ptr, layout) }
534
+ }
535
+
536
+ unsafe fn grow (
537
+ & self ,
538
+ ptr : core:: ptr:: NonNull < u8 > ,
539
+ old_layout : Layout ,
540
+ new_layout : Layout ,
541
+ ) -> Result < core:: ptr:: NonNull < [ u8 ] > , AllocError > {
542
+ // SAFETY: the safety contract must be upheld by the caller
543
+ unsafe { self . 0 . grow ( ptr, old_layout, new_layout) }
544
+ }
545
+
546
+ unsafe fn grow_zeroed (
547
+ & self ,
548
+ ptr : core:: ptr:: NonNull < u8 > ,
549
+ old_layout : Layout ,
550
+ new_layout : Layout ,
551
+ ) -> Result < core:: ptr:: NonNull < [ u8 ] > , AllocError > {
552
+ // SAFETY: the safety contract must be upheld by the caller
553
+ unsafe { self . 0 . grow_zeroed ( ptr, old_layout, new_layout) }
554
+ }
555
+
556
+ unsafe fn shrink (
557
+ & self ,
558
+ ptr : core:: ptr:: NonNull < u8 > ,
559
+ old_layout : Layout ,
560
+ new_layout : Layout ,
561
+ ) -> Result < core:: ptr:: NonNull < [ u8 ] > , AllocError > {
562
+ // SAFETY: the safety contract must be upheld by the caller
563
+ unsafe { self . 0 . shrink ( ptr, old_layout, new_layout) }
564
+ }
565
+
566
+ fn by_ref ( & self ) -> & Self
567
+ where
568
+ Self : Sized ,
569
+ {
570
+ self
571
+ }
572
+
573
+ type ErrorHandling = Fatal ;
574
+ }
575
+
576
+ /// Wrapper around an existing allocator allowing one to
577
+ /// use an infallible allocator as a fallible one.
578
+ #[ unstable( feature = "allocator_api" , issue = "32838" ) ]
579
+ #[ cfg( all( not( no_global_oom_handling) , not( test) ) ) ]
580
+ #[ derive( Debug ) ]
581
+ pub struct FallibleAdapter < A : Allocator < ErrorHandling = Fatal > > ( pub A ) ;
582
+
583
+ #[ unstable( feature = "allocator_api" , issue = "32838" ) ]
584
+ #[ cfg( all( not( no_global_oom_handling) , not( test) ) ) ]
585
+ unsafe impl < A : Allocator < ErrorHandling = Fatal > > Allocator for FallibleAdapter < A > {
586
+ fn allocate ( & self , layout : Layout ) -> Result < core:: ptr:: NonNull < [ u8 ] > , AllocError > {
587
+ self . 0 . allocate ( layout)
588
+ }
589
+
590
+ fn allocate_zeroed ( & self , layout : Layout ) -> Result < core:: ptr:: NonNull < [ u8 ] > , AllocError > {
591
+ self . 0 . allocate_zeroed ( layout)
592
+ }
593
+
594
+ unsafe fn deallocate ( & self , ptr : core:: ptr:: NonNull < u8 > , layout : Layout ) {
595
+ // SAFETY: the safety contract must be upheld by the caller
596
+ unsafe { self . 0 . deallocate ( ptr, layout) }
597
+ }
598
+
599
+ unsafe fn grow (
600
+ & self ,
601
+ ptr : core:: ptr:: NonNull < u8 > ,
602
+ old_layout : Layout ,
603
+ new_layout : Layout ,
604
+ ) -> Result < core:: ptr:: NonNull < [ u8 ] > , AllocError > {
605
+ // SAFETY: the safety contract must be upheld by the caller
606
+ unsafe { self . 0 . grow ( ptr, old_layout, new_layout) }
607
+ }
608
+
609
+ unsafe fn grow_zeroed (
610
+ & self ,
611
+ ptr : core:: ptr:: NonNull < u8 > ,
612
+ old_layout : Layout ,
613
+ new_layout : Layout ,
614
+ ) -> Result < core:: ptr:: NonNull < [ u8 ] > , AllocError > {
615
+ // SAFETY: the safety contract must be upheld by the caller
616
+ unsafe { self . 0 . grow_zeroed ( ptr, old_layout, new_layout) }
617
+ }
618
+
619
+ unsafe fn shrink (
620
+ & self ,
621
+ ptr : core:: ptr:: NonNull < u8 > ,
622
+ old_layout : Layout ,
623
+ new_layout : Layout ,
624
+ ) -> Result < core:: ptr:: NonNull < [ u8 ] > , AllocError > {
625
+ // SAFETY: the safety contract must be upheld by the caller
626
+ unsafe { self . 0 . shrink ( ptr, old_layout, new_layout) }
627
+ }
628
+
629
+ fn by_ref ( & self ) -> & Self
630
+ where
631
+ Self : Sized ,
632
+ {
633
+ self
634
+ }
635
+
636
+ type ErrorHandling = Fallible ;
637
+ }
638
+
639
+ #[ cfg( test) ]
640
+ pub use std:: alloc:: { FallibleAdapter , Fatal , FatalAdapter , HandleAllocError } ;
641
+
452
642
#[ cfg( not( no_global_oom_handling) ) ]
453
643
use crate :: collections:: { TryReserveError , TryReserveErrorKind } ;
454
644
0 commit comments