@@ -12,10 +12,15 @@ use std::fmt;
12
12
13
13
use std:: convert:: TryInto ;
14
14
15
+ /// The value of an inserted drop flag.
15
16
#[ derive( Debug , PartialEq , Eq , Copy , Clone ) ]
16
17
pub 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 ,
19
24
}
20
25
21
26
impl DropFlagState {
@@ -27,23 +32,42 @@ impl DropFlagState {
27
32
}
28
33
}
29
34
35
+ /// Describes how/if a value should be dropped.
30
36
#[ derive( Debug ) ]
31
37
pub enum DropStyle {
38
+ /// The value is already dead at the drop location, no drop will be executed.
32
39
Dead ,
40
+
41
+ /// The value is known to always be initialized at the drop location, drop will always be
42
+ /// executed.
33
43
Static ,
44
+
45
+ /// Whether the value needs to be dropped depends on its drop flag.
34
46
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.
35
53
Open ,
36
54
}
37
55
56
+ /// Which drop flags to affect/check with an operation.
38
57
#[ derive( Debug ) ]
39
58
pub enum DropFlagMode {
59
+ /// Only affect the top-level drop flag, not that of any contained fields.
40
60
Shallow ,
61
+ /// Affect all nested drop flags in addition to the top-level one.
41
62
Deep ,
42
63
}
43
64
65
+ /// Describes if unwinding is necessary and where to unwind to if a panic occurs.
44
66
#[ derive( Copy , Clone , Debug ) ]
45
67
pub enum Unwind {
68
+ /// Unwind to this block.
46
69
To ( BasicBlock ) ,
70
+ /// Already in an unwind path, any panic will cause an abort.
47
71
InCleanup ,
48
72
}
49
73
@@ -74,20 +98,58 @@ impl Unwind {
74
98
}
75
99
76
100
pub 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) `()`.
77
106
type Path : Copy + fmt:: Debug ;
78
107
108
+ // Accessors
109
+
79
110
fn patch ( & mut self ) -> & mut MirPatch < ' tcx > ;
80
111
fn body ( & self ) -> & ' a Body < ' tcx > ;
81
112
fn tcx ( & self ) -> TyCtxt < ' tcx > ;
82
113
fn param_env ( & self ) -> ty:: ParamEnv < ' tcx > ;
83
114
115
+ // Drop logic
116
+
117
+ /// Returns how `path` should be dropped, given `mode`.
84
118
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).
85
121
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.
86
127
fn clear_drop_flag ( & mut self , location : Location , path : Self :: Path , mode : DropFlagMode ) ;
87
128
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.
88
134
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.
89
141
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.
90
146
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.
91
153
fn array_subpath ( & self , path : Self :: Path , index : u32 , size : u32 ) -> Option < Self :: Path > ;
92
154
}
93
155
@@ -106,6 +168,14 @@ where
106
168
unwind : Unwind ,
107
169
}
108
170
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.
109
179
pub fn elaborate_drop < ' b , ' tcx , D > (
110
180
elaborator : & mut D ,
111
181
source_info : SourceInfo ,
@@ -346,9 +416,7 @@ where
346
416
let interior = self . tcx ( ) . mk_place_deref ( self . place ) ;
347
417
let interior_path = self . elaborator . deref_subpath ( self . path ) ;
348
418
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 ) ;
352
420
let unwind_succ =
353
421
self . unwind . map ( |unwind| self . box_free_block ( adt, substs, unwind, Unwind :: InCleanup ) ) ;
354
422
@@ -829,6 +897,8 @@ where
829
897
self . drop_flag_test_block ( drop_block, succ, unwind)
830
898
}
831
899
900
+ /// Creates a block that resets the drop flag. If `mode` is deep, all children drop flags will
901
+ /// also be cleared.
832
902
fn drop_flag_reset_block (
833
903
& mut self ,
834
904
mode : DropFlagMode ,
@@ -850,13 +920,15 @@ where
850
920
851
921
fn elaborated_drop_block ( & mut self ) -> BasicBlock {
852
922
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 ) ;
856
924
self . elaborate_drop ( blk) ;
857
925
blk
858
926
}
859
927
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.
860
932
fn box_free_block (
861
933
& mut self ,
862
934
adt : & ' tcx ty:: AdtDef ,
@@ -868,6 +940,8 @@ where
868
940
self . drop_flag_test_block ( block, target, unwind)
869
941
}
870
942
943
+ /// Creates a block that frees the backing memory of a `Box` (without dropping the contained
944
+ /// value).
871
945
fn unelaborated_free_block (
872
946
& mut self ,
873
947
adt : & ' tcx ty:: AdtDef ,
@@ -914,6 +988,11 @@ where
914
988
self . new_block ( unwind, block)
915
989
}
916
990
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.
917
996
fn drop_flag_test_block (
918
997
& mut self ,
919
998
on_set : BasicBlock ,
0 commit comments