@@ -15,7 +15,7 @@ use rustc::middle::region::ROOT_CODE_EXTENT;
15
15
use rustc:: mir:: * ;
16
16
use rustc:: mir:: transform:: MirSource ;
17
17
use rustc:: ty:: { self , Ty } ;
18
- use rustc:: ty:: subst:: Subst ;
18
+ use rustc:: ty:: subst:: { Kind , Subst } ;
19
19
use rustc:: ty:: maps:: Providers ;
20
20
21
21
use rustc_data_structures:: indexed_vec:: { IndexVec , Idx } ;
@@ -25,10 +25,13 @@ use syntax::ast;
25
25
use syntax_pos:: Span ;
26
26
27
27
use std:: cell:: RefCell ;
28
+ use std:: fmt;
28
29
use std:: iter;
29
30
use std:: mem;
30
31
31
32
use transform:: { add_call_guards, no_landing_pads, simplify} ;
33
+ use util:: elaborate_drops:: { self , DropElaborator , DropStyle , DropFlagMode } ;
34
+ use util:: patch:: MirPatch ;
32
35
33
36
pub fn provide ( providers : & mut Providers ) {
34
37
providers. mir_shims = make_shim;
@@ -101,6 +104,9 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
101
104
None
102
105
)
103
106
}
107
+ ty:: InstanceDef :: DropGlue ( def_id, ty) => {
108
+ build_drop_shim ( tcx, & param_env, def_id, ty)
109
+ }
104
110
ty:: InstanceDef :: Intrinsic ( _) => {
105
111
bug ! ( "creating shims from intrinsics ({:?}) is unsupported" , instance)
106
112
}
@@ -143,6 +149,129 @@ fn local_decls_for_sig<'tcx>(sig: &ty::FnSig<'tcx>)
143
149
. collect ( )
144
150
}
145
151
152
+ fn build_drop_shim < ' a , ' tcx > ( tcx : ty:: TyCtxt < ' a , ' tcx , ' tcx > ,
153
+ param_env : & ty:: ParameterEnvironment < ' tcx > ,
154
+ def_id : DefId ,
155
+ ty : Option < Ty < ' tcx > > )
156
+ -> Mir < ' tcx >
157
+ {
158
+ debug ! ( "build_drop_shim(def_id={:?}, ty={:?})" , def_id, ty) ;
159
+
160
+ let substs = if let Some ( ty) = ty {
161
+ tcx. mk_substs ( iter:: once ( Kind :: from ( ty) ) )
162
+ } else {
163
+ param_env. free_substs
164
+ } ;
165
+ let fn_ty = tcx. item_type ( def_id) . subst ( tcx, substs) ;
166
+ let sig = tcx. erase_late_bound_regions ( & fn_ty. fn_sig ( ) ) ;
167
+ let span = tcx. def_span ( def_id) ;
168
+
169
+ let source_info = SourceInfo { span, scope : ARGUMENT_VISIBILITY_SCOPE } ;
170
+
171
+ let return_block = BasicBlock :: new ( 1 ) ;
172
+ let mut blocks = IndexVec :: new ( ) ;
173
+ let block = |blocks : & mut IndexVec < _ , _ > , kind| {
174
+ blocks. push ( BasicBlockData {
175
+ statements : vec ! [ ] ,
176
+ terminator : Some ( Terminator { source_info, kind } ) ,
177
+ is_cleanup : false
178
+ } )
179
+ } ;
180
+ block ( & mut blocks, TerminatorKind :: Goto { target : return_block } ) ;
181
+ block ( & mut blocks, TerminatorKind :: Return ) ;
182
+
183
+ let mut mir = Mir :: new (
184
+ blocks,
185
+ IndexVec :: from_elem_n (
186
+ VisibilityScopeData { span : span, parent_scope : None } , 1
187
+ ) ,
188
+ IndexVec :: new ( ) ,
189
+ sig. output ( ) ,
190
+ local_decls_for_sig ( & sig) ,
191
+ sig. inputs ( ) . len ( ) ,
192
+ vec ! [ ] ,
193
+ span
194
+ ) ;
195
+
196
+ if let Some ( ..) = ty {
197
+ let patch = {
198
+ let mut elaborator = DropShimElaborator {
199
+ mir : & mir,
200
+ patch : MirPatch :: new ( & mir) ,
201
+ tcx, param_env
202
+ } ;
203
+ let dropee = Lvalue :: Projection (
204
+ box Projection {
205
+ base : Lvalue :: Local ( Local :: new ( 1 +0 ) ) ,
206
+ elem : ProjectionElem :: Deref
207
+ }
208
+ ) ;
209
+ let resume_block = elaborator. patch . resume_block ( ) ;
210
+ elaborate_drops:: elaborate_drop (
211
+ & mut elaborator,
212
+ source_info,
213
+ false ,
214
+ & dropee,
215
+ ( ) ,
216
+ return_block,
217
+ Some ( resume_block) ,
218
+ START_BLOCK
219
+ ) ;
220
+ elaborator. patch
221
+ } ;
222
+ patch. apply ( & mut mir) ;
223
+ }
224
+
225
+ mir
226
+ }
227
+
228
+ pub struct DropShimElaborator < ' a , ' tcx : ' a > {
229
+ mir : & ' a Mir < ' tcx > ,
230
+ patch : MirPatch < ' tcx > ,
231
+ tcx : ty:: TyCtxt < ' a , ' tcx , ' tcx > ,
232
+ param_env : & ' a ty:: ParameterEnvironment < ' tcx > ,
233
+ }
234
+
235
+ impl < ' a , ' tcx > fmt:: Debug for DropShimElaborator < ' a , ' tcx > {
236
+ fn fmt ( & self , _f : & mut fmt:: Formatter ) -> Result < ( ) , fmt:: Error > {
237
+ Ok ( ( ) )
238
+ }
239
+ }
240
+
241
+ impl < ' a , ' tcx > DropElaborator < ' a , ' tcx > for DropShimElaborator < ' a , ' tcx > {
242
+ type Path = ( ) ;
243
+
244
+ fn patch ( & mut self ) -> & mut MirPatch < ' tcx > { & mut self . patch }
245
+ fn mir ( & self ) -> & ' a Mir < ' tcx > { self . mir }
246
+ fn tcx ( & self ) -> ty:: TyCtxt < ' a , ' tcx , ' tcx > { self . tcx }
247
+ fn param_env ( & self ) -> & ' a ty:: ParameterEnvironment < ' tcx > { self . param_env }
248
+
249
+ fn drop_style ( & self , _path : Self :: Path , mode : DropFlagMode ) -> DropStyle {
250
+ if let DropFlagMode :: Shallow = mode {
251
+ DropStyle :: Static
252
+ } else {
253
+ DropStyle :: Open
254
+ }
255
+ }
256
+
257
+ fn get_drop_flag ( & mut self , _path : Self :: Path ) -> Option < Operand < ' tcx > > {
258
+ None
259
+ }
260
+
261
+ fn clear_drop_flag ( & mut self , _location : Location , _path : Self :: Path , _mode : DropFlagMode ) {
262
+ }
263
+
264
+ fn field_subpath ( & self , _path : Self :: Path , _field : Field ) -> Option < Self :: Path > {
265
+ None
266
+ }
267
+ fn deref_subpath ( & self , _path : Self :: Path ) -> Option < Self :: Path > {
268
+ None
269
+ }
270
+ fn downcast_subpath ( & self , _path : Self :: Path , _variant : usize ) -> Option < Self :: Path > {
271
+ Some ( ( ) )
272
+ }
273
+ }
274
+
146
275
/// Build a "call" shim for `def_id`. The shim calls the
147
276
/// function specified by `call_kind`, first adjusting its first
148
277
/// argument according to `rcvr_adjustment`.
@@ -162,7 +291,6 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
162
291
def_id, rcvr_adjustment, call_kind, untuple_args) ;
163
292
164
293
let fn_ty = tcx. item_type ( def_id) . subst ( tcx, param_env. free_substs ) ;
165
- // Not normalizing here without a param env.
166
294
let sig = tcx. erase_late_bound_regions ( & fn_ty. fn_sig ( ) ) ;
167
295
let span = tcx. def_span ( def_id) ;
168
296
0 commit comments