@@ -15,7 +15,7 @@ use rustc::middle::region::ROOT_CODE_EXTENT;
1515use rustc:: mir:: * ;
1616use rustc:: mir:: transform:: MirSource ;
1717use rustc:: ty:: { self , Ty } ;
18- use rustc:: ty:: subst:: Subst ;
18+ use rustc:: ty:: subst:: { Kind , Subst } ;
1919use rustc:: ty:: maps:: Providers ;
2020
2121use rustc_data_structures:: indexed_vec:: { IndexVec , Idx } ;
@@ -25,10 +25,13 @@ use syntax::ast;
2525use syntax_pos:: Span ;
2626
2727use std:: cell:: RefCell ;
28+ use std:: fmt;
2829use std:: iter;
2930use std:: mem;
3031
3132use transform:: { add_call_guards, no_landing_pads, simplify} ;
33+ use util:: elaborate_drops:: { self , DropElaborator , DropStyle , DropFlagMode } ;
34+ use util:: patch:: MirPatch ;
3235
3336pub fn provide ( providers : & mut Providers ) {
3437 providers. mir_shims = make_shim;
@@ -101,6 +104,9 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
101104 None
102105 )
103106 }
107+ ty:: InstanceDef :: DropGlue ( def_id, ty) => {
108+ build_drop_shim ( tcx, & param_env, def_id, ty)
109+ }
104110 ty:: InstanceDef :: Intrinsic ( _) => {
105111 bug ! ( "creating shims from intrinsics ({:?}) is unsupported" , instance)
106112 }
@@ -143,6 +149,129 @@ fn local_decls_for_sig<'tcx>(sig: &ty::FnSig<'tcx>)
143149 . collect ( )
144150}
145151
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+
146275/// Build a "call" shim for `def_id`. The shim calls the
147276/// function specified by `call_kind`, first adjusting its first
148277/// argument according to `rcvr_adjustment`.
@@ -162,7 +291,6 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
162291 def_id, rcvr_adjustment, call_kind, untuple_args) ;
163292
164293 let fn_ty = tcx. item_type ( def_id) . subst ( tcx, param_env. free_substs ) ;
165- // Not normalizing here without a param env.
166294 let sig = tcx. erase_late_bound_regions ( & fn_ty. fn_sig ( ) ) ;
167295 let span = tcx. def_span ( def_id) ;
168296
0 commit comments