@@ -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