@@ -191,16 +191,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
191
191
exit_block. unit ( )
192
192
}
193
193
ExprKind :: Call { ty, fun, args, from_hir_call } => {
194
- let intrinsic = match ty. sty {
194
+ let ( fn_def_id , intrinsic) = match ty. sty {
195
195
ty:: FnDef ( def_id, _) => {
196
196
let f = ty. fn_sig ( this. hir . tcx ( ) ) ;
197
197
if f. abi ( ) == Abi :: RustIntrinsic || f. abi ( ) == Abi :: PlatformIntrinsic {
198
- Some ( this. hir . tcx ( ) . item_name ( def_id) . as_str ( ) )
198
+ ( Some ( def_id ) , Some ( this. hir . tcx ( ) . item_name ( def_id) . as_str ( ) ) )
199
199
} else {
200
- None
200
+ ( Some ( def_id ) , None )
201
201
}
202
202
}
203
- _ => None ,
203
+ _ => ( None , None ) ,
204
204
} ;
205
205
let intrinsic = intrinsic. as_ref ( ) . map ( |s| & s[ ..] ) ;
206
206
let fun = unpack ! ( block = this. as_local_operand( block, fun) ) ;
@@ -237,26 +237,51 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
237
237
. map ( |arg| unpack ! ( block = this. as_local_operand( block, arg) ) )
238
238
. collect ( ) ;
239
239
240
+ let drop_location = if fn_def_id. is_some ( )
241
+ && this. hir . tcx ( ) . lang_items ( ) . drop_fn ( ) == fn_def_id
242
+ {
243
+ assert_eq ! ( args. len( ) , 1 , "drop() must have exactly one argument" ) ;
244
+ match & args[ 0 ] {
245
+ Operand :: Move ( place) => Some ( place. clone ( ) ) ,
246
+ _ => None ,
247
+ }
248
+ } else {
249
+ None
250
+ } ;
251
+
240
252
let success = this. cfg . start_new_block ( ) ;
241
253
let cleanup = this. diverge_cleanup ( ) ;
242
- this. cfg . terminate (
243
- block,
244
- source_info,
245
- TerminatorKind :: Call {
246
- func : fun,
247
- args,
248
- cleanup : Some ( cleanup) ,
249
- // FIXME(varkor): replace this with an uninhabitedness-based check.
250
- // This requires getting access to the current module to call
251
- // `tcx.is_ty_uninhabited_from`, which is currently tricky to do.
252
- destination : if expr. ty . is_never ( ) {
253
- None
254
- } else {
255
- Some ( ( destination. clone ( ) , success) )
254
+
255
+ if let Some ( location) = drop_location {
256
+ this. cfg . terminate (
257
+ block,
258
+ source_info,
259
+ TerminatorKind :: Drop {
260
+ location,
261
+ target : success,
262
+ unwind : Some ( cleanup)
256
263
} ,
257
- from_hir_call,
258
- } ,
259
- ) ;
264
+ ) ;
265
+ } else {
266
+ this. cfg . terminate (
267
+ block,
268
+ source_info,
269
+ TerminatorKind :: Call {
270
+ func : fun,
271
+ args,
272
+ cleanup : Some ( cleanup) ,
273
+ // FIXME(varkor): replace this with an uninhabitedness-based check.
274
+ // This requires getting access to the current module to call
275
+ // `tcx.is_ty_uninhabited_from`, which is currently tricky to do.
276
+ destination : if expr. ty . is_never ( ) {
277
+ None
278
+ } else {
279
+ Some ( ( destination. clone ( ) , success) )
280
+ } ,
281
+ from_hir_call,
282
+ } ,
283
+ ) ;
284
+ }
260
285
success. unit ( )
261
286
}
262
287
}
0 commit comments