@@ -36,6 +36,7 @@ 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 ;
@@ -582,54 +583,113 @@ impl <'gcx: 'tcx, 'tcx> Canonicalize<'gcx, 'tcx> for Ty<'tcx> {
582583 }
583584}
584585
586+ extern {
587+ /// A dummy type used to force Slice to by unsized without requiring fat pointers
588+ type OpaqueSliceContents ;
589+ }
590+
585591/// A wrapper for slices with the additional invariant
586592/// that the slice is interned and no other slice with
587593/// the same contents can exist in the same context.
588- /// This means we can use pointer + length for both
594+ /// This means we can use pointer for both
589595/// equality comparisons and hashing.
590- #[ derive( Debug , RustcEncodable ) ]
591- pub struct Slice < T > ( [ T ] ) ;
596+ #[ repr( C ) ]
597+ pub struct Slice < T > {
598+ len : usize ,
599+ data : [ T ; 0 ] ,
600+ opaque : OpaqueSliceContents ,
601+ }
602+
603+ impl < T : Copy > Slice < T > {
604+ #[ inline]
605+ fn from_arena < ' tcx > ( arena : & ' tcx SyncDroplessArena , slice : & [ T ] ) -> & ' tcx Slice < T > {
606+ assert ! ( !mem:: needs_drop:: <T >( ) ) ;
607+ assert ! ( mem:: size_of:: <T >( ) != 0 ) ;
608+ assert ! ( slice. len( ) != 0 ) ;
609+
610+ // Align up the size of the len (usize) field
611+ let align = mem:: align_of :: < T > ( ) ;
612+ let align_mask = align - 1 ;
613+ let offset = mem:: size_of :: < usize > ( ) ;
614+ let offset = ( offset + align_mask) & !align_mask;
615+
616+ let size = offset + slice. len ( ) * mem:: size_of :: < T > ( ) ;
617+
618+ let mem = arena. alloc_raw (
619+ size,
620+ cmp:: max ( mem:: align_of :: < T > ( ) , mem:: align_of :: < usize > ( ) ) ) ;
621+ unsafe {
622+ let result = & mut * ( mem. as_mut_ptr ( ) as * mut Slice < T > ) ;
623+ // Write the length
624+ result. len = slice. len ( ) ;
625+
626+ // Write the elements
627+ let arena_slice = slice:: from_raw_parts_mut ( result. data . as_mut_ptr ( ) , result. len ) ;
628+ arena_slice. copy_from_slice ( slice) ;
629+
630+ result
631+ }
632+ }
633+ }
634+
635+ impl < T : fmt:: Debug > fmt:: Debug for Slice < T > {
636+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
637+ ( * * self ) . fmt ( f)
638+ }
639+ }
640+
641+ impl < T : Encodable > Encodable for Slice < T > {
642+ #[ inline]
643+ fn encode < S : Encoder > ( & self , s : & mut S ) -> Result < ( ) , S :: Error > {
644+ ( * * self ) . encode ( s)
645+ }
646+ }
592647
593648impl < T > Ord for Slice < T > where T : Ord {
594649 fn cmp ( & self , other : & Slice < T > ) -> Ordering {
595650 if self == other { Ordering :: Equal } else {
596- <[ T ] as Ord >:: cmp ( & self . 0 , & other. 0 )
651+ <[ T ] as Ord >:: cmp ( & * * self , & * * other)
597652 }
598653 }
599654}
600655
601656impl < T > PartialOrd for Slice < T > where T : PartialOrd {
602657 fn partial_cmp ( & self , other : & Slice < T > ) -> Option < Ordering > {
603658 if self == other { Some ( Ordering :: Equal ) } else {
604- <[ T ] as PartialOrd >:: partial_cmp ( & self . 0 , & other. 0 )
659+ <[ T ] as PartialOrd >:: partial_cmp ( & * * self , & * * other)
605660 }
606661 }
607662}
608663
609- impl < T > PartialEq for Slice < T > {
664+ impl < T : PartialEq > PartialEq for Slice < T > {
610665 #[ inline]
611666 fn eq ( & self , other : & Slice < T > ) -> bool {
612- ( & self . 0 as * const [ T ] ) == ( & other. 0 as * const [ T ] )
667+ ( self as * const _ ) == ( other as * const _ )
613668 }
614669}
615- impl < T > Eq for Slice < T > { }
670+ impl < T : Eq > Eq for Slice < T > { }
616671
617672impl < T > Hash for Slice < T > {
673+ #[ inline]
618674 fn hash < H : Hasher > ( & self , s : & mut H ) {
619- ( self . as_ptr ( ) , self . len ( ) ) . hash ( s)
675+ ( self as * const Slice < T > ) . hash ( s)
620676 }
621677}
622678
623679impl < T > Deref for Slice < T > {
624680 type Target = [ T ] ;
681+ #[ inline( always) ]
625682 fn deref ( & self ) -> & [ T ] {
626- & self . 0
683+ unsafe {
684+ slice:: from_raw_parts ( self . data . as_ptr ( ) , self . len )
685+ }
627686 }
628687}
629688
630689impl < ' a , T > IntoIterator for & ' a Slice < T > {
631690 type Item = & ' a T ;
632691 type IntoIter = <& ' a [ T ] as IntoIterator >:: IntoIter ;
692+ #[ inline( always) ]
633693 fn into_iter ( self ) -> Self :: IntoIter {
634694 self [ ..] . iter ( )
635695 }
@@ -638,9 +698,14 @@ impl<'a, T> IntoIterator for &'a Slice<T> {
638698impl < ' tcx > serialize:: UseSpecializedDecodable for & ' tcx Slice < Ty < ' tcx > > { }
639699
640700impl < T > Slice < T > {
701+ #[ inline( always) ]
641702 pub fn empty < ' a > ( ) -> & ' a Slice < T > {
703+ #[ repr( align( 64 ) , C ) ]
704+ struct EmptySlice ( [ u8 ; 64 ] ) ;
705+ static EMPTY_SLICE : EmptySlice = EmptySlice ( [ 0 ; 64 ] ) ;
706+ assert ! ( mem:: align_of:: <T >( ) <= 64 ) ;
642707 unsafe {
643- mem :: transmute ( slice :: from_raw_parts ( 0x1 as * const T , 0 ) )
708+ & * ( & EMPTY_SLICE as * const _ as * const Slice < T > )
644709 }
645710 }
646711}
0 commit comments