@@ -36,12 +36,14 @@ use ty::util::{IntTypeExt, Discr};
3636use ty:: walk:: TypeWalker ;
3737use util:: captures:: Captures ;
3838use util:: nodemap:: { NodeSet , DefIdMap , FxHashMap } ;
39+ use arena:: SyncDroplessArena ;
3940
4041use serialize:: { self , Encodable , Encoder } ;
4142use std:: cell:: RefCell ;
4243use std:: cmp;
4344use std:: fmt;
4445use std:: hash:: { Hash , Hasher } ;
46+ use std:: marker:: PhantomData ;
4547use std:: ops:: Deref ;
4648use rustc_data_structures:: sync:: Lrc ;
4749use std:: slice;
@@ -570,38 +572,106 @@ impl <'gcx: 'tcx, 'tcx> Canonicalize<'gcx, 'tcx> for Ty<'tcx> {
570572 }
571573}
572574
575+ extern {
576+ /// A dummy type used to force Slice to by unsized without requiring fat pointers
577+ type OpaqueSliceContents ;
578+ }
579+
573580/// A wrapper for slices with the additional invariant
574581/// that the slice is interned and no other slice with
575582/// the same contents can exist in the same context.
576583/// This means we can use pointer + length for both
577584/// equality comparisons and hashing.
578- #[ derive( Debug , RustcEncodable ) ]
579- pub struct Slice < T > ( [ T ] ) ;
585+ pub struct Slice < T > ( PhantomData < T > , OpaqueSliceContents ) ;
580586
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 > {
582642 #[ inline]
583643 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
585647 }
586648}
587- impl < T > Eq for Slice < T > { }
649+ impl < T : Eq > Eq for Slice < T > { }
588650
589651impl < T > Hash for Slice < T > {
652+ #[ inline]
590653 fn hash < H : Hasher > ( & self , s : & mut H ) {
591654 ( self . as_ptr ( ) , self . len ( ) ) . hash ( s)
592655 }
593656}
594657
595658impl < T > Deref for Slice < T > {
596659 type Target = [ T ] ;
660+ #[ inline( always) ]
597661 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+ }
599668 }
600669}
601670
602671impl < ' a , T > IntoIterator for & ' a Slice < T > {
603672 type Item = & ' a T ;
604673 type IntoIter = <& ' a [ T ] as IntoIterator >:: IntoIter ;
674+ #[ inline( always) ]
605675 fn into_iter ( self ) -> Self :: IntoIter {
606676 self [ ..] . iter ( )
607677 }
@@ -610,9 +680,14 @@ impl<'a, T> IntoIterator for &'a Slice<T> {
610680impl < ' tcx > serialize:: UseSpecializedDecodable for & ' tcx Slice < Ty < ' tcx > > { }
611681
612682impl < T > Slice < T > {
683+ #[ inline( always) ]
613684 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 ) ;
614689 unsafe {
615- mem :: transmute ( slice :: from_raw_parts ( 0x1 as * const T , 0 ) )
690+ & * ( & EMPTY_SLICE as * const _ as * const Slice < T > )
616691 }
617692 }
618693}
0 commit comments