@@ -12,10 +12,15 @@ use std::fmt;
1212
1313use std:: convert:: TryInto ;
1414
15+ /// The value of an inserted drop flag.
1516#[ derive( Debug , PartialEq , Eq , Copy , Clone ) ]
1617pub enum DropFlagState {
17- Present , // i.e., initialized
18- Absent , // i.e., deinitialized or "moved"
18+ /// The tracked value is initialized and needs to be dropped when leaving its scope.
19+ Present ,
20+
21+ /// The tracked value is uninitialized or was moved out of and does not need to be dropped when
22+ /// leaving its scope.
23+ Absent ,
1924}
2025
2126impl DropFlagState {
@@ -27,23 +32,42 @@ impl DropFlagState {
2732 }
2833}
2934
35+ /// Describes how/if a value should be dropped.
3036#[ derive( Debug ) ]
3137pub enum DropStyle {
38+ /// The value is already dead at the drop location, no drop will be executed.
3239 Dead ,
40+
41+ /// The value is known to always be initialized at the drop location, drop will always be
42+ /// executed.
3343 Static ,
44+
45+ /// Whether the value needs to be dropped depends on its drop flag.
3446 Conditional ,
47+
48+ /// An "open" drop is one where only the fields of a value are dropped.
49+ ///
50+ /// For example, this happens when moving out of a struct field: The rest of the struct will be
51+ /// dropped in such an "open" drop. It is also used to generate drop glue for the individual
52+ /// components of a value, for example for dropping array elements.
3553 Open ,
3654}
3755
56+ /// Which drop flags to affect/check with an operation.
3857#[ derive( Debug ) ]
3958pub enum DropFlagMode {
59+ /// Only affect the top-level drop flag, not that of any contained fields.
4060 Shallow ,
61+ /// Affect all nested drop flags in addition to the top-level one.
4162 Deep ,
4263}
4364
65+ /// Describes if unwinding is necessary and where to unwind to if a panic occurs.
4466#[ derive( Copy , Clone , Debug ) ]
4567pub enum Unwind {
68+ /// Unwind to this block.
4669 To ( BasicBlock ) ,
70+ /// Already in an unwind path, any panic will cause an abort.
4771 InCleanup ,
4872}
4973
@@ -74,20 +98,58 @@ impl Unwind {
7498}
7599
76100pub trait DropElaborator < ' a , ' tcx > : fmt:: Debug {
101+ /// The type representing paths that can be moved out of.
102+ ///
103+ /// Users can move out of individual fields of a struct, such as `a.b.c`. This type is used to
104+ /// represent such move paths. Sometimes tracking individual move paths is not necessary, in
105+ /// which case this may be set to (for example) `()`.
77106 type Path : Copy + fmt:: Debug ;
78107
108+ // Accessors
109+
79110 fn patch ( & mut self ) -> & mut MirPatch < ' tcx > ;
80111 fn body ( & self ) -> & ' a Body < ' tcx > ;
81112 fn tcx ( & self ) -> TyCtxt < ' tcx > ;
82113 fn param_env ( & self ) -> ty:: ParamEnv < ' tcx > ;
83114
115+ // Drop logic
116+
117+ /// Returns how `path` should be dropped, given `mode`.
84118 fn drop_style ( & self , path : Self :: Path , mode : DropFlagMode ) -> DropStyle ;
119+
120+ /// Returns the drop flag of `path` as a MIR `Operand` (or `None` if `path` has no drop flag).
85121 fn get_drop_flag ( & mut self , path : Self :: Path ) -> Option < Operand < ' tcx > > ;
122+
123+ /// Modifies the MIR patch so that the drop flag of `path` (if any) is cleared at `location`.
124+ ///
125+ /// If `mode` is deep, drop flags of all child paths should also be cleared by inserting
126+ /// additional statements.
86127 fn clear_drop_flag ( & mut self , location : Location , path : Self :: Path , mode : DropFlagMode ) ;
87128
129+ // Subpaths
130+
131+ /// Returns the subpath of a field of `path` (or `None` if there is no dedicated subpath).
132+ ///
133+ /// If this returns `None`, `field` will not get a dedicated drop flag.
88134 fn field_subpath ( & self , path : Self :: Path , field : Field ) -> Option < Self :: Path > ;
135+
136+ /// Returns the subpath of a dereference of `path` (or `None` if there is no dedicated subpath).
137+ ///
138+ /// If this returns `None`, `*path` will not get a dedicated drop flag.
139+ ///
140+ /// This is only relevant for `Box<T>`, where the contained `T` can be moved out of the box.
89141 fn deref_subpath ( & self , path : Self :: Path ) -> Option < Self :: Path > ;
142+
143+ /// Returns the subpath of downcasting `path` to one of its variants.
144+ ///
145+ /// If this returns `None`, the downcast of `path` will not get a dedicated drop flag.
90146 fn downcast_subpath ( & self , path : Self :: Path , variant : VariantIdx ) -> Option < Self :: Path > ;
147+
148+ /// Returns the subpath of indexing a fixed-size array `path`.
149+ ///
150+ /// If this returns `None`, elements of `path` will not get a dedicated drop flag.
151+ ///
152+ /// This is only relevant for array patterns, which can move out of individual array elements.
91153 fn array_subpath ( & self , path : Self :: Path , index : u32 , size : u32 ) -> Option < Self :: Path > ;
92154}
93155
@@ -106,6 +168,14 @@ where
106168 unwind : Unwind ,
107169}
108170
171+ /// "Elaborates" a drop of `place`/`path` and patches `bb`'s terminator to execute it.
172+ ///
173+ /// The passed `elaborator` is used to determine what should happen at the drop terminator. It
174+ /// decides whether the drop can be statically determined or whether it needs a dynamic drop flag,
175+ /// and whether the drop is "open", ie. should be expanded to drop all subfields of the dropped
176+ /// value.
177+ ///
178+ /// When this returns, the MIR patch in the `elaborator` contains the necessary changes.
109179pub fn elaborate_drop < ' b , ' tcx , D > (
110180 elaborator : & mut D ,
111181 source_info : SourceInfo ,
@@ -346,9 +416,7 @@ where
346416 let interior = self . tcx ( ) . mk_place_deref ( self . place ) ;
347417 let interior_path = self . elaborator . deref_subpath ( self . path ) ;
348418
349- let succ = self . succ ; // FIXME(#43234)
350- let unwind = self . unwind ;
351- let succ = self . box_free_block ( adt, substs, succ, unwind) ;
419+ let succ = self . box_free_block ( adt, substs, self . succ , self . unwind ) ;
352420 let unwind_succ =
353421 self . unwind . map ( |unwind| self . box_free_block ( adt, substs, unwind, Unwind :: InCleanup ) ) ;
354422
@@ -829,6 +897,8 @@ where
829897 self . drop_flag_test_block ( drop_block, succ, unwind)
830898 }
831899
900+ /// Creates a block that resets the drop flag. If `mode` is deep, all children drop flags will
901+ /// also be cleared.
832902 fn drop_flag_reset_block (
833903 & mut self ,
834904 mode : DropFlagMode ,
@@ -850,13 +920,15 @@ where
850920
851921 fn elaborated_drop_block ( & mut self ) -> BasicBlock {
852922 debug ! ( "elaborated_drop_block({:?})" , self ) ;
853- let unwind = self . unwind ; // FIXME(#43234)
854- let succ = self . succ ;
855- let blk = self . drop_block ( succ, unwind) ;
923+ let blk = self . drop_block ( self . succ , self . unwind ) ;
856924 self . elaborate_drop ( blk) ;
857925 blk
858926 }
859927
928+ /// Creates a block that frees the backing memory of a `Box` if its drop is required (either
929+ /// statically or by checking its drop flag).
930+ ///
931+ /// The contained value will not be dropped.
860932 fn box_free_block (
861933 & mut self ,
862934 adt : & ' tcx ty:: AdtDef ,
@@ -868,6 +940,8 @@ where
868940 self . drop_flag_test_block ( block, target, unwind)
869941 }
870942
943+ /// Creates a block that frees the backing memory of a `Box` (without dropping the contained
944+ /// value).
871945 fn unelaborated_free_block (
872946 & mut self ,
873947 adt : & ' tcx ty:: AdtDef ,
@@ -914,6 +988,11 @@ where
914988 self . new_block ( unwind, block)
915989 }
916990
991+ /// Returns the block to jump to in order to test the drop flag and execute the drop.
992+ ///
993+ /// Depending on the required `DropStyle`, this might be a generated block with an `if`
994+ /// terminator (for dynamic/open drops), or it might be `on_set` or `on_unset` itself, in case
995+ /// the drop can be statically determined.
917996 fn drop_flag_test_block (
918997 & mut self ,
919998 on_set : BasicBlock ,
0 commit comments