@@ -252,14 +252,15 @@ use core::hash::{Hash, Hasher};
252
252
use core:: intrinsics:: abort;
253
253
use core:: marker;
254
254
use core:: marker:: Unsize ;
255
- use core:: mem:: { self , forget, size_of , size_of_val, uninitialized} ;
255
+ use core:: mem:: { self , forget, size_of_val, uninitialized} ;
256
256
use core:: ops:: Deref ;
257
257
use core:: ops:: CoerceUnsized ;
258
258
use core:: ptr:: { self , Shared } ;
259
259
use core:: convert:: From ;
260
260
261
261
use heap:: { Heap , Alloc , Layout , box_free} ;
262
- use raw_vec:: RawVec ;
262
+ use string:: String ;
263
+ use vec:: Vec ;
263
264
264
265
struct RcBox < T : ?Sized > {
265
266
strong : Cell < usize > ,
@@ -421,64 +422,6 @@ impl<T> Rc<T> {
421
422
}
422
423
}
423
424
424
- impl Rc < str > {
425
- /// Constructs a new `Rc<str>` from a string slice.
426
- #[ doc( hidden) ]
427
- #[ unstable( feature = "rustc_private" ,
428
- reason = "for internal use in rustc" ,
429
- issue = "27812" ) ]
430
- pub fn __from_str ( value : & str ) -> Rc < str > {
431
- unsafe {
432
- // Allocate enough space for `RcBox<str>`.
433
- let aligned_len = 2 + ( value. len ( ) + size_of :: < usize > ( ) - 1 ) / size_of :: < usize > ( ) ;
434
- let vec = RawVec :: < usize > :: with_capacity ( aligned_len) ;
435
- let ptr = vec. ptr ( ) ;
436
- forget ( vec) ;
437
- // Initialize fields of `RcBox<str>`.
438
- * ptr. offset ( 0 ) = 1 ; // strong: Cell::new(1)
439
- * ptr. offset ( 1 ) = 1 ; // weak: Cell::new(1)
440
- ptr:: copy_nonoverlapping ( value. as_ptr ( ) , ptr. offset ( 2 ) as * mut u8 , value. len ( ) ) ;
441
- // Combine the allocation address and the string length into a fat pointer to `RcBox`.
442
- let rcbox_ptr: * mut RcBox < str > = mem:: transmute ( [ ptr as usize , value. len ( ) ] ) ;
443
- assert ! ( aligned_len * size_of:: <usize >( ) == size_of_val( & * rcbox_ptr) ) ;
444
- Rc { ptr : Shared :: new_unchecked ( rcbox_ptr) }
445
- }
446
- }
447
- }
448
-
449
- impl < T > Rc < [ T ] > {
450
- /// Constructs a new `Rc<[T]>` from a `Box<[T]>`.
451
- #[ doc( hidden) ]
452
- #[ unstable( feature = "rustc_private" ,
453
- reason = "for internal use in rustc" ,
454
- issue = "27812" ) ]
455
- pub fn __from_array ( value : Box < [ T ] > ) -> Rc < [ T ] > {
456
- unsafe {
457
- let ptr: * mut RcBox < [ T ] > =
458
- mem:: transmute ( [ mem:: align_of :: < RcBox < [ T ; 1 ] > > ( ) , value. len ( ) ] ) ;
459
- // FIXME(custom-DST): creating this invalid &[T] is dubiously defined,
460
- // we should have a better way of getting the size/align
461
- // of a DST from its unsized part.
462
- let ptr = Heap . alloc ( Layout :: for_value ( & * ptr) )
463
- . unwrap_or_else ( |e| Heap . oom ( e) ) ;
464
- let ptr: * mut RcBox < [ T ] > = mem:: transmute ( [ ptr as usize , value. len ( ) ] ) ;
465
-
466
- // Initialize the new RcBox.
467
- ptr:: write ( & mut ( * ptr) . strong , Cell :: new ( 1 ) ) ;
468
- ptr:: write ( & mut ( * ptr) . weak , Cell :: new ( 1 ) ) ;
469
- ptr:: copy_nonoverlapping (
470
- value. as_ptr ( ) ,
471
- & mut ( * ptr) . value as * mut [ T ] as * mut T ,
472
- value. len ( ) ) ;
473
-
474
- // Free the original allocation without freeing its (moved) contents.
475
- box_free ( Box :: into_raw ( value) ) ;
476
-
477
- Rc { ptr : Shared :: new_unchecked ( ptr as * mut _ ) }
478
- }
479
- }
480
- }
481
-
482
425
impl < T : ?Sized > Rc < T > {
483
426
/// Creates a new [`Weak`][weak] pointer to this value.
484
427
///
@@ -665,6 +608,140 @@ impl<T: Clone> Rc<T> {
665
608
}
666
609
}
667
610
611
+ impl < T : ?Sized > Rc < T > {
612
+ // Allocates an `RcBox<T>` with sufficient space for an unsized value
613
+ unsafe fn allocate_for_ptr ( ptr : * const T ) -> * mut RcBox < T > {
614
+ // Create a fake RcBox to find allocation size and alignment
615
+ let fake_ptr = ptr as * mut RcBox < T > ;
616
+
617
+ let layout = Layout :: for_value ( & * fake_ptr) ;
618
+
619
+ let mem = Heap . alloc ( layout)
620
+ . unwrap_or_else ( |e| Heap . oom ( e) ) ;
621
+
622
+ // Initialize the real RcBox
623
+ let inner = set_data_ptr ( ptr as * mut T , mem) as * mut RcBox < T > ;
624
+
625
+ ptr:: write ( & mut ( * inner) . strong , Cell :: new ( 1 ) ) ;
626
+ ptr:: write ( & mut ( * inner) . weak , Cell :: new ( 1 ) ) ;
627
+
628
+ inner
629
+ }
630
+
631
+ fn from_box ( v : Box < T > ) -> Rc < T > {
632
+ unsafe {
633
+ let bptr = Box :: into_raw ( v) ;
634
+
635
+ let value_size = size_of_val ( & * bptr) ;
636
+ let ptr = Self :: allocate_for_ptr ( bptr) ;
637
+
638
+ // Copy value as bytes
639
+ ptr:: copy_nonoverlapping (
640
+ bptr as * const T as * const u8 ,
641
+ & mut ( * ptr) . value as * mut _ as * mut u8 ,
642
+ value_size) ;
643
+
644
+ // Free the allocation without dropping its contents
645
+ box_free ( bptr) ;
646
+
647
+ Rc { ptr : Shared :: new_unchecked ( ptr) }
648
+ }
649
+ }
650
+ }
651
+
652
+ // Sets the data pointer of a `?Sized` raw pointer.
653
+ //
654
+ // For a slice/trait object, this sets the `data` field and leaves the rest
655
+ // unchanged. For a sized raw pointer, this simply sets the pointer.
656
+ unsafe fn set_data_ptr < T : ?Sized , U > ( mut ptr : * mut T , data : * mut U ) -> * mut T {
657
+ ptr:: write ( & mut ptr as * mut _ as * mut * mut u8 , data as * mut u8 ) ;
658
+ ptr
659
+ }
660
+
661
+ impl < T > Rc < [ T ] > {
662
+ // Copy elements from slice into newly allocated Rc<[T]>
663
+ //
664
+ // Unsafe because the caller must either take ownership or bind `T: Copy`
665
+ unsafe fn copy_from_slice ( v : & [ T ] ) -> Rc < [ T ] > {
666
+ let v_ptr = v as * const [ T ] ;
667
+ let ptr = Self :: allocate_for_ptr ( v_ptr) ;
668
+
669
+ ptr:: copy_nonoverlapping (
670
+ v. as_ptr ( ) ,
671
+ & mut ( * ptr) . value as * mut [ T ] as * mut T ,
672
+ v. len ( ) ) ;
673
+
674
+ Rc { ptr : Shared :: new_unchecked ( ptr) }
675
+ }
676
+ }
677
+
678
+ trait RcFromSlice < T > {
679
+ fn from_slice ( slice : & [ T ] ) -> Self ;
680
+ }
681
+
682
+ impl < T : Clone > RcFromSlice < T > for Rc < [ T ] > {
683
+ #[ inline]
684
+ default fn from_slice ( v : & [ T ] ) -> Self {
685
+ // Panic guard while cloning T elements.
686
+ // In the event of a panic, elements that have been written
687
+ // into the new RcBox will be dropped, then the memory freed.
688
+ struct Guard < T > {
689
+ mem : * mut u8 ,
690
+ elems : * mut T ,
691
+ layout : Layout ,
692
+ n_elems : usize ,
693
+ }
694
+
695
+ impl < T > Drop for Guard < T > {
696
+ fn drop ( & mut self ) {
697
+ use core:: slice:: from_raw_parts_mut;
698
+
699
+ unsafe {
700
+ let slice = from_raw_parts_mut ( self . elems , self . n_elems ) ;
701
+ ptr:: drop_in_place ( slice) ;
702
+
703
+ Heap . dealloc ( self . mem , self . layout . clone ( ) ) ;
704
+ }
705
+ }
706
+ }
707
+
708
+ unsafe {
709
+ let v_ptr = v as * const [ T ] ;
710
+ let ptr = Self :: allocate_for_ptr ( v_ptr) ;
711
+
712
+ let mem = ptr as * mut _ as * mut u8 ;
713
+ let layout = Layout :: for_value ( & * ptr) ;
714
+
715
+ // Pointer to first element
716
+ let elems = & mut ( * ptr) . value as * mut [ T ] as * mut T ;
717
+
718
+ let mut guard = Guard {
719
+ mem : mem,
720
+ elems : elems,
721
+ layout : layout,
722
+ n_elems : 0 ,
723
+ } ;
724
+
725
+ for ( i, item) in v. iter ( ) . enumerate ( ) {
726
+ ptr:: write ( elems. offset ( i as isize ) , item. clone ( ) ) ;
727
+ guard. n_elems += 1 ;
728
+ }
729
+
730
+ // All clear. Forget the guard so it doesn't free the new RcBox.
731
+ forget ( guard) ;
732
+
733
+ Rc { ptr : Shared :: new_unchecked ( ptr) }
734
+ }
735
+ }
736
+ }
737
+
738
+ impl < T : Copy > RcFromSlice < T > for Rc < [ T ] > {
739
+ #[ inline]
740
+ fn from_slice ( v : & [ T ] ) -> Self {
741
+ unsafe { Rc :: copy_from_slice ( v) }
742
+ }
743
+ }
744
+
668
745
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
669
746
impl < T : ?Sized > Deref for Rc < T > {
670
747
type Target = T ;
@@ -959,6 +1036,53 @@ impl<T> From<T> for Rc<T> {
959
1036
}
960
1037
}
961
1038
1039
+ #[ stable( feature = "shared_from_slice" , since = "1.21.0" ) ]
1040
+ impl < ' a , T : Clone > From < & ' a [ T ] > for Rc < [ T ] > {
1041
+ #[ inline]
1042
+ fn from ( v : & [ T ] ) -> Rc < [ T ] > {
1043
+ <Self as RcFromSlice < T > >:: from_slice ( v)
1044
+ }
1045
+ }
1046
+
1047
+ #[ stable( feature = "shared_from_slice" , since = "1.21.0" ) ]
1048
+ impl < ' a > From < & ' a str > for Rc < str > {
1049
+ #[ inline]
1050
+ fn from ( v : & str ) -> Rc < str > {
1051
+ unsafe { mem:: transmute ( <Rc < [ u8 ] > >:: from ( v. as_bytes ( ) ) ) }
1052
+ }
1053
+ }
1054
+
1055
+ #[ stable( feature = "shared_from_slice" , since = "1.21.0" ) ]
1056
+ impl From < String > for Rc < str > {
1057
+ #[ inline]
1058
+ fn from ( v : String ) -> Rc < str > {
1059
+ Rc :: from ( & v[ ..] )
1060
+ }
1061
+ }
1062
+
1063
+ #[ stable( feature = "shared_from_slice" , since = "1.21.0" ) ]
1064
+ impl < T : ?Sized > From < Box < T > > for Rc < T > {
1065
+ #[ inline]
1066
+ fn from ( v : Box < T > ) -> Rc < T > {
1067
+ Rc :: from_box ( v)
1068
+ }
1069
+ }
1070
+
1071
+ #[ stable( feature = "shared_from_slice" , since = "1.21.0" ) ]
1072
+ impl < T > From < Vec < T > > for Rc < [ T ] > {
1073
+ #[ inline]
1074
+ fn from ( mut v : Vec < T > ) -> Rc < [ T ] > {
1075
+ unsafe {
1076
+ let rc = Rc :: copy_from_slice ( & v) ;
1077
+
1078
+ // Allow the Vec to free its memory, but not destroy its contents
1079
+ v. set_len ( 0 ) ;
1080
+
1081
+ rc
1082
+ }
1083
+ }
1084
+ }
1085
+
962
1086
/// `Weak` is a version of [`Rc`] that holds a non-owning reference to the
963
1087
/// managed value. The value is accessed by calling [`upgrade`] on the `Weak`
964
1088
/// pointer, which returns an [`Option`]`<`[`Rc`]`<T>>`.
@@ -1465,6 +1589,113 @@ mod tests {
1465
1589
assert ! ( Rc :: ptr_eq( & five, & same_five) ) ;
1466
1590
assert ! ( !Rc :: ptr_eq( & five, & other_five) ) ;
1467
1591
}
1592
+
1593
+ #[ test]
1594
+ fn test_from_str ( ) {
1595
+ let r: Rc < str > = Rc :: from ( "foo" ) ;
1596
+
1597
+ assert_eq ! ( & r[ ..] , "foo" ) ;
1598
+ }
1599
+
1600
+ #[ test]
1601
+ fn test_copy_from_slice ( ) {
1602
+ let s: & [ u32 ] = & [ 1 , 2 , 3 ] ;
1603
+ let r: Rc < [ u32 ] > = Rc :: from ( s) ;
1604
+
1605
+ assert_eq ! ( & r[ ..] , [ 1 , 2 , 3 ] ) ;
1606
+ }
1607
+
1608
+ #[ test]
1609
+ fn test_clone_from_slice ( ) {
1610
+ #[ derive( Clone , Debug , Eq , PartialEq ) ]
1611
+ struct X ( u32 ) ;
1612
+
1613
+ let s: & [ X ] = & [ X ( 1 ) , X ( 2 ) , X ( 3 ) ] ;
1614
+ let r: Rc < [ X ] > = Rc :: from ( s) ;
1615
+
1616
+ assert_eq ! ( & r[ ..] , s) ;
1617
+ }
1618
+
1619
+ #[ test]
1620
+ #[ should_panic]
1621
+ fn test_clone_from_slice_panic ( ) {
1622
+ use std:: string:: { String , ToString } ;
1623
+
1624
+ struct Fail ( u32 , String ) ;
1625
+
1626
+ impl Clone for Fail {
1627
+ fn clone ( & self ) -> Fail {
1628
+ if self . 0 == 2 {
1629
+ panic ! ( ) ;
1630
+ }
1631
+ Fail ( self . 0 , self . 1 . clone ( ) )
1632
+ }
1633
+ }
1634
+
1635
+ let s: & [ Fail ] = & [
1636
+ Fail ( 0 , "foo" . to_string ( ) ) ,
1637
+ Fail ( 1 , "bar" . to_string ( ) ) ,
1638
+ Fail ( 2 , "baz" . to_string ( ) ) ,
1639
+ ] ;
1640
+
1641
+ // Should panic, but not cause memory corruption
1642
+ let _r: Rc < [ Fail ] > = Rc :: from ( s) ;
1643
+ }
1644
+
1645
+ #[ test]
1646
+ fn test_from_box ( ) {
1647
+ let b: Box < u32 > = box 123 ;
1648
+ let r: Rc < u32 > = Rc :: from ( b) ;
1649
+
1650
+ assert_eq ! ( * r, 123 ) ;
1651
+ }
1652
+
1653
+ #[ test]
1654
+ fn test_from_box_str ( ) {
1655
+ use std:: string:: String ;
1656
+
1657
+ let s = String :: from ( "foo" ) . into_boxed_str ( ) ;
1658
+ let r: Rc < str > = Rc :: from ( s) ;
1659
+
1660
+ assert_eq ! ( & r[ ..] , "foo" ) ;
1661
+ }
1662
+
1663
+ #[ test]
1664
+ fn test_from_box_slice ( ) {
1665
+ let s = vec ! [ 1 , 2 , 3 ] . into_boxed_slice ( ) ;
1666
+ let r: Rc < [ u32 ] > = Rc :: from ( s) ;
1667
+
1668
+ assert_eq ! ( & r[ ..] , [ 1 , 2 , 3 ] ) ;
1669
+ }
1670
+
1671
+ #[ test]
1672
+ fn test_from_box_trait ( ) {
1673
+ use std:: fmt:: Display ;
1674
+ use std:: string:: ToString ;
1675
+
1676
+ let b: Box < Display > = box 123 ;
1677
+ let r: Rc < Display > = Rc :: from ( b) ;
1678
+
1679
+ assert_eq ! ( r. to_string( ) , "123" ) ;
1680
+ }
1681
+
1682
+ #[ test]
1683
+ fn test_from_box_trait_zero_sized ( ) {
1684
+ use std:: fmt:: Debug ;
1685
+
1686
+ let b: Box < Debug > = box ( ) ;
1687
+ let r: Rc < Debug > = Rc :: from ( b) ;
1688
+
1689
+ assert_eq ! ( format!( "{:?}" , r) , "()" ) ;
1690
+ }
1691
+
1692
+ #[ test]
1693
+ fn test_from_vec ( ) {
1694
+ let v = vec ! [ 1 , 2 , 3 ] ;
1695
+ let r: Rc < [ u32 ] > = Rc :: from ( v) ;
1696
+
1697
+ assert_eq ! ( & r[ ..] , [ 1 , 2 , 3 ] ) ;
1698
+ }
1468
1699
}
1469
1700
1470
1701
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
0 commit comments