@@ -36,12 +36,14 @@ use ty::util::{IntTypeExt, Discr};
36
36
use ty:: walk:: TypeWalker ;
37
37
use util:: captures:: Captures ;
38
38
use util:: nodemap:: { NodeSet , DefIdMap , FxHashMap } ;
39
+ use arena:: SyncDroplessArena ;
39
40
40
41
use serialize:: { self , Encodable , Encoder } ;
41
42
use std:: cell:: RefCell ;
42
43
use std:: cmp;
43
44
use std:: fmt;
44
45
use std:: hash:: { Hash , Hasher } ;
46
+ use std:: marker:: PhantomData ;
45
47
use std:: ops:: Deref ;
46
48
use rustc_data_structures:: sync:: Lrc ;
47
49
use std:: slice;
@@ -570,38 +572,106 @@ impl <'gcx: 'tcx, 'tcx> Canonicalize<'gcx, 'tcx> for Ty<'tcx> {
570
572
}
571
573
}
572
574
575
+ extern {
576
+ /// A dummy type used to force Slice to by unsized without requiring fat pointers
577
+ type OpaqueSliceContents ;
578
+ }
579
+
573
580
/// A wrapper for slices with the additional invariant
574
581
/// that the slice is interned and no other slice with
575
582
/// the same contents can exist in the same context.
576
583
/// This means we can use pointer + length for both
577
584
/// equality comparisons and hashing.
578
- #[ derive( Debug , RustcEncodable ) ]
579
- pub struct Slice < T > ( [ T ] ) ;
585
+ pub struct Slice < T > ( PhantomData < T > , OpaqueSliceContents ) ;
580
586
581
- impl < T > PartialEq for Slice < T > {
587
+ impl < T > Slice < T > {
588
+ /// Returns the offset of the array
589
+ #[ inline( always) ]
590
+ fn offset ( ) -> usize {
591
+ // Align up the size of the len (usize) field
592
+ let align = mem:: align_of :: < T > ( ) ;
593
+ let align_mask = align - 1 ;
594
+ let offset = mem:: size_of :: < usize > ( ) ;
595
+ ( offset + align_mask) & !align_mask
596
+ }
597
+ }
598
+
599
+ impl < T : Copy > Slice < T > {
600
+ #[ inline]
601
+ fn from_arena < ' tcx > ( arena : & ' tcx SyncDroplessArena , slice : & [ T ] ) -> & ' tcx Slice < T > {
602
+ assert ! ( !mem:: needs_drop:: <T >( ) ) ;
603
+ assert ! ( mem:: size_of:: <T >( ) != 0 ) ;
604
+ assert ! ( slice. len( ) != 0 ) ;
605
+
606
+ let offset = Slice :: < T > :: offset ( ) ;
607
+ let size = offset + slice. len ( ) * mem:: size_of :: < T > ( ) ;
608
+
609
+ let mem: * mut u8 = arena. alloc_raw (
610
+ size,
611
+ cmp:: max ( mem:: align_of :: < T > ( ) , mem:: align_of :: < usize > ( ) ) ) . as_mut_ptr ( ) ;
612
+
613
+ unsafe {
614
+ // Write the length
615
+ * ( mem as * mut usize ) = slice. len ( ) ;
616
+
617
+ // Write the elements
618
+ let arena_slice = slice:: from_raw_parts_mut (
619
+ mem. offset ( offset as isize ) as * mut T ,
620
+ slice. len ( ) ) ;
621
+ arena_slice. copy_from_slice ( slice) ;
622
+
623
+ & * ( mem as * const Slice < T > )
624
+ }
625
+ }
626
+ }
627
+
628
+ impl < T : fmt:: Debug > fmt:: Debug for Slice < T > {
629
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
630
+ ( * * self ) . fmt ( f)
631
+ }
632
+ }
633
+
634
+ impl < T : Encodable > Encodable for Slice < T > {
635
+ #[ inline]
636
+ fn encode < S : Encoder > ( & self , s : & mut S ) -> Result < ( ) , S :: Error > {
637
+ ( * * self ) . encode ( s)
638
+ }
639
+ }
640
+
641
+ impl < T : PartialEq > PartialEq for Slice < T > {
582
642
#[ inline]
583
643
fn eq ( & self , other : & Slice < T > ) -> bool {
584
- ( & self . 0 as * const [ T ] ) == ( & other. 0 as * const [ T ] )
644
+ let r = ( self as * const _ ) == ( other as * const _ ) ;
645
+ assert_eq ! ( r, * * self == * * other) ;
646
+ r
585
647
}
586
648
}
587
- impl < T > Eq for Slice < T > { }
649
+ impl < T : Eq > Eq for Slice < T > { }
588
650
589
651
impl < T > Hash for Slice < T > {
652
+ #[ inline]
590
653
fn hash < H : Hasher > ( & self , s : & mut H ) {
591
654
( self . as_ptr ( ) , self . len ( ) ) . hash ( s)
592
655
}
593
656
}
594
657
595
658
impl < T > Deref for Slice < T > {
596
659
type Target = [ T ] ;
660
+ #[ inline( always) ]
597
661
fn deref ( & self ) -> & [ T ] {
598
- & self . 0
662
+ unsafe {
663
+ let raw = self as * const _ as * const u8 ;
664
+ let len = * ( raw as * const usize ) ;
665
+ let slice = raw. offset ( Slice :: < T > :: offset ( ) as isize ) ;
666
+ slice:: from_raw_parts ( slice as * const T , len)
667
+ }
599
668
}
600
669
}
601
670
602
671
impl < ' a , T > IntoIterator for & ' a Slice < T > {
603
672
type Item = & ' a T ;
604
673
type IntoIter = <& ' a [ T ] as IntoIterator >:: IntoIter ;
674
+ #[ inline( always) ]
605
675
fn into_iter ( self ) -> Self :: IntoIter {
606
676
self [ ..] . iter ( )
607
677
}
@@ -610,9 +680,14 @@ impl<'a, T> IntoIterator for &'a Slice<T> {
610
680
impl < ' tcx > serialize:: UseSpecializedDecodable for & ' tcx Slice < Ty < ' tcx > > { }
611
681
612
682
impl < T > Slice < T > {
683
+ #[ inline( always) ]
613
684
pub fn empty < ' a > ( ) -> & ' a Slice < T > {
685
+ #[ repr( align( 64 ) , C ) ]
686
+ struct EmptySlice ( [ usize ; 64 ] ) ;
687
+ static EMPTY_SLICE : EmptySlice = EmptySlice ( [ 0 ; 64 ] ) ;
688
+ assert ! ( mem:: align_of:: <T >( ) <= 64 ) ;
614
689
unsafe {
615
- mem :: transmute ( slice :: from_raw_parts ( 0x1 as * const T , 0 ) )
690
+ & * ( & EMPTY_SLICE as * const _ as * const Slice < T > )
616
691
}
617
692
}
618
693
}
0 commit comments