@@ -67,6 +67,31 @@ use trans::type_of;
67
67
68
68
type Hint = attr:: ReprAttr ;
69
69
70
+ // Representation of the context surrounding an unsized type. I want
71
+ // to be able to track the drop flags that are injected by trans.
72
+ #[ derive( Clone , Copy , PartialEq , Debug ) ]
73
+ pub struct TypeContext {
74
+ prefix : Type ,
75
+ needs_drop_flag : bool ,
76
+ }
77
+
78
+ impl TypeContext {
79
+ pub fn prefix ( & self ) -> Type { self . prefix }
80
+ pub fn needs_drop_flag ( & self ) -> bool { self . needs_drop_flag }
81
+
82
+ fn direct ( t : Type ) -> TypeContext {
83
+ TypeContext { prefix : t, needs_drop_flag : false }
84
+ }
85
+ fn may_need_drop_flag ( t : Type , needs_drop_flag : bool ) -> TypeContext {
86
+ TypeContext { prefix : t, needs_drop_flag : needs_drop_flag }
87
+ }
88
+ pub fn to_string ( self ) -> String {
89
+ let TypeContext { prefix, needs_drop_flag } = self ;
90
+ format ! ( "TypeContext {{ prefix: {}, needs_drop_flag: {} }}" ,
91
+ prefix. to_string( ) , needs_drop_flag)
92
+ }
93
+ }
94
+
70
95
/// Representations.
71
96
#[ derive( Eq , PartialEq , Debug ) ]
72
97
pub enum Repr < ' tcx > {
@@ -125,7 +150,7 @@ pub struct Struct<'tcx> {
125
150
pub align : u32 ,
126
151
pub sized : bool ,
127
152
pub packed : bool ,
128
- pub fields : Vec < Ty < ' tcx > >
153
+ pub fields : Vec < Ty < ' tcx > > ,
129
154
}
130
155
131
156
/// Convenience for `represent_type`. There should probably be more or
@@ -681,18 +706,30 @@ fn ensure_enum_fits_in_address_space<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
681
706
/// and fill in the actual contents in a second pass to prevent
682
707
/// unbounded recursion; see also the comments in `trans::type_of`.
683
708
pub fn type_of < ' a , ' tcx > ( cx : & CrateContext < ' a , ' tcx > , r : & Repr < ' tcx > ) -> Type {
684
- generic_type_of ( cx, r, None , false , false )
709
+ let c = generic_type_of ( cx, r, None , false , false , false ) ;
710
+ assert ! ( !c. needs_drop_flag) ;
711
+ c. prefix
685
712
}
713
+
714
+
686
715
// Pass dst=true if the type you are passing is a DST. Yes, we could figure
687
716
// this out, but if you call this on an unsized type without realising it, you
688
717
// are going to get the wrong type (it will not include the unsized parts of it).
689
718
pub fn sizing_type_of < ' a , ' tcx > ( cx : & CrateContext < ' a , ' tcx > ,
690
719
r : & Repr < ' tcx > , dst : bool ) -> Type {
691
- generic_type_of ( cx, r, None , true , dst)
720
+ let c = generic_type_of ( cx, r, None , true , dst, false ) ;
721
+ assert ! ( !c. needs_drop_flag) ;
722
+ c. prefix
723
+ }
724
+ pub fn sizing_type_context_of < ' a , ' tcx > ( cx : & CrateContext < ' a , ' tcx > ,
725
+ r : & Repr < ' tcx > , dst : bool ) -> TypeContext {
726
+ generic_type_of ( cx, r, None , true , dst, true )
692
727
}
693
728
pub fn incomplete_type_of < ' a , ' tcx > ( cx : & CrateContext < ' a , ' tcx > ,
694
729
r : & Repr < ' tcx > , name : & str ) -> Type {
695
- generic_type_of ( cx, r, Some ( name) , false , false )
730
+ let c = generic_type_of ( cx, r, Some ( name) , false , false , false ) ;
731
+ assert ! ( !c. needs_drop_flag) ;
732
+ c. prefix
696
733
}
697
734
pub fn finish_type_of < ' a , ' tcx > ( cx : & CrateContext < ' a , ' tcx > ,
698
735
r : & Repr < ' tcx > , llty : & mut Type ) {
@@ -708,20 +745,50 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
708
745
r : & Repr < ' tcx > ,
709
746
name : Option < & str > ,
710
747
sizing : bool ,
711
- dst : bool ) -> Type {
748
+ dst : bool ,
749
+ delay_drop_flag : bool ) -> TypeContext {
750
+ debug ! ( "adt::generic_type_of r: {:?} name: {:?} sizing: {} dst: {} delay_drop_flag: {}" ,
751
+ r, name, sizing, dst, delay_drop_flag) ;
712
752
match * r {
713
- CEnum ( ity, _, _) => ll_inttype ( cx, ity) ,
714
- RawNullablePointer { nnty, .. } => type_of:: sizing_type_of ( cx, nnty) ,
715
- Univariant ( ref st, _) | StructWrappedNullablePointer { nonnull : ref st, .. } => {
753
+ CEnum ( ity, _, _) => TypeContext :: direct ( ll_inttype ( cx, ity) ) ,
754
+ RawNullablePointer { nnty, .. } =>
755
+ TypeContext :: direct ( type_of:: sizing_type_of ( cx, nnty) ) ,
756
+ StructWrappedNullablePointer { nonnull : ref st, .. } => {
757
+ match name {
758
+ None => {
759
+ TypeContext :: direct (
760
+ Type :: struct_ ( cx, & struct_llfields ( cx, st, sizing, dst) ,
761
+ st. packed ) )
762
+ }
763
+ Some ( name) => {
764
+ assert_eq ! ( sizing, false ) ;
765
+ TypeContext :: direct ( Type :: named_struct ( cx, name) )
766
+ }
767
+ }
768
+ }
769
+ Univariant ( ref st, dtor_needed) => {
770
+ let dtor_needed = dtor_needed != 0 ;
716
771
match name {
717
772
None => {
718
- Type :: struct_ ( cx, & struct_llfields ( cx, st, sizing, dst) ,
719
- st. packed )
773
+ let mut fields = struct_llfields ( cx, st, sizing, dst) ;
774
+ if delay_drop_flag && dtor_needed {
775
+ fields. pop ( ) ;
776
+ }
777
+ TypeContext :: may_need_drop_flag (
778
+ Type :: struct_ ( cx, & fields,
779
+ st. packed ) ,
780
+ delay_drop_flag && dtor_needed)
781
+ }
782
+ Some ( name) => {
783
+ // Hypothesis: named_struct's can never need a
784
+ // drop flag. (... needs validation.)
785
+ assert_eq ! ( sizing, false ) ;
786
+ TypeContext :: direct ( Type :: named_struct ( cx, name) )
720
787
}
721
- Some ( name) => { assert_eq ! ( sizing, false ) ; Type :: named_struct ( cx, name) }
722
788
}
723
789
}
724
- General ( ity, ref sts, _) => {
790
+ General ( ity, ref sts, dtor_needed) => {
791
+ let dtor_needed = dtor_needed != 0 ;
725
792
// We need a representation that has:
726
793
// * The alignment of the most-aligned field
727
794
// * The size of the largest variant (rounded up to that alignment)
@@ -753,15 +820,25 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
753
820
} ;
754
821
assert_eq ! ( machine:: llalign_of_min( cx, fill_ty) , align) ;
755
822
assert_eq ! ( align_s % discr_size, 0 ) ;
756
- let fields = [ discr_ty,
757
- Type :: array ( & discr_ty, align_s / discr_size - 1 ) ,
758
- fill_ty] ;
823
+ let mut fields: Vec < Type > =
824
+ [ discr_ty,
825
+ Type :: array ( & discr_ty, align_s / discr_size - 1 ) ,
826
+ fill_ty] . iter ( ) . cloned ( ) . collect ( ) ;
827
+ if delay_drop_flag && dtor_needed {
828
+ fields. pop ( ) ;
829
+ }
759
830
match name {
760
- None => Type :: struct_ ( cx, & fields[ ..] , false ) ,
831
+ None => {
832
+ TypeContext :: may_need_drop_flag (
833
+ Type :: struct_ ( cx, & fields[ ..] , false ) ,
834
+ delay_drop_flag && dtor_needed)
835
+ }
761
836
Some ( name) => {
762
837
let mut llty = Type :: named_struct ( cx, name) ;
763
838
llty. set_struct_body ( & fields[ ..] , false ) ;
764
- llty
839
+ TypeContext :: may_need_drop_flag (
840
+ llty,
841
+ delay_drop_flag && dtor_needed)
765
842
}
766
843
}
767
844
}
0 commit comments