Skip to content

Commit b0a4808

Browse files
committed
Remove direct variant-dispatch entirely from trans_struct_drop.
This addresses to-do in my code, and simplifies this method a lot to boot. (The necessary enum dispatch has now effectively been shifted entirely into the scheduled cleanup code for the enum contents.)
1 parent d5acb55 commit b0a4808

File tree

1 file changed

+19
-59
lines changed

1 file changed

+19
-59
lines changed

src/librustc_trans/trans/glue.rs

+19-59
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ use trans::callee;
3030
use trans::cleanup;
3131
use trans::cleanup::CleanupMethods;
3232
use trans::common::*;
33-
use trans::datum;
3433
use trans::debuginfo::DebugLoc;
3534
use trans::declare;
3635
use trans::expr;
@@ -361,75 +360,36 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
361360
substs: &subst::Substs<'tcx>)
362361
-> Block<'blk, 'tcx>
363362
{
364-
let repr = adt::represent_type(bcx.ccx(), t);
363+
debug!("trans_struct_drop t: {}", bcx.ty_to_string(t));
365364

366365
// Find and call the actual destructor
367-
let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did, t,
368-
class_did, substs);
366+
let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did, t, class_did, substs);
369367

370-
// The first argument is the "self" argument for drop
368+
// Class dtors have no explicit args, so the params should
369+
// just consist of the environment (self).
371370
let params = unsafe {
372371
let ty = Type::from_ref(llvm::LLVMTypeOf(dtor_addr));
373372
ty.element_type().func_params()
374373
};
374+
assert_eq!(params.len(), 1);
375375

376-
let fty = ty::lookup_item_type(bcx.tcx(), dtor_did).ty.subst(bcx.tcx(), substs);
377-
let self_ty = match fty.sty {
378-
ty::ty_bare_fn(_, ref f) => {
379-
let sig = ty::erase_late_bound_regions(bcx.tcx(), &f.sig);
380-
assert!(sig.inputs.len() == 1);
381-
sig.inputs[0]
382-
}
383-
_ => bcx.sess().bug(&format!("Expected function type, found {}",
384-
bcx.ty_to_string(fty)))
385-
};
386-
387-
let (struct_data, info) = if type_is_sized(bcx.tcx(), t) {
388-
(v0, None)
389-
} else {
390-
let data = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]);
391-
let info = GEPi(bcx, v0, &[0, abi::FAT_PTR_EXTRA]);
392-
(Load(bcx, data), Some(Load(bcx, info)))
393-
};
376+
// Be sure to put the contents into a scope so we can use an invoke
377+
// instruction to call the user destructor but still call the field
378+
// destructors if the user destructor panics.
379+
//
380+
// FIXME (#14875) panic-in-drop semantics might be unsupported; we
381+
// might well consider changing below to more direct code.
382+
let contents_scope = bcx.fcx.push_custom_cleanup_scope();
394383

395-
debug!("trans_struct_drop t: {} fty: {} self_ty: {}",
396-
bcx.ty_to_string(t), bcx.ty_to_string(fty), bcx.ty_to_string(self_ty));
397-
// TODO: surely no reason to keep dispatching on variants here.
398-
adt::fold_variants(bcx, &*repr, struct_data, |variant_cx, struct_info, value| {
399-
debug!("trans_struct_drop fold_variant: struct_info: {:?}", struct_info);
400-
// Be sure to put the enum contents into a scope so we can use an invoke
401-
// instruction to call the user destructor but still call the field
402-
// destructors if the user destructor panics.
403-
let field_scope = variant_cx.fcx.push_custom_cleanup_scope();
404-
variant_cx.fcx.schedule_drop_enum_contents(cleanup::CustomScope(field_scope), v0, t);
405-
406-
// Class dtors have no explicit args, so the params should
407-
// just consist of the environment (self).
408-
assert_eq!(params.len(), 1);
409-
let self_arg = if type_is_fat_ptr(bcx.tcx(), self_ty) {
410-
// The dtor expects a fat pointer, so make one, even if we have to fake it.
411-
let scratch = datum::rvalue_scratch_datum(bcx, t, "__fat_ptr_drop_self");
412-
Store(bcx, value, GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
413-
Store(bcx,
414-
// If we just had a thin pointer, make a fat pointer by sticking
415-
// null where we put the unsizing info. This works because t
416-
// is a sized type, so we will only unpack the fat pointer, never
417-
// use the fake info.
418-
info.unwrap_or(C_null(Type::i8p(bcx.ccx()))),
419-
GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_EXTRA]));
420-
PointerCast(variant_cx, scratch.val, params[0])
421-
} else {
422-
PointerCast(variant_cx, value, params[0])
423-
};
384+
// Issue #23611: schedule cleanup of contents, re-inspecting the
385+
// discriminant (if any) in case of variant swap in drop code.
386+
bcx.fcx.schedule_drop_enum_contents(cleanup::CustomScope(contents_scope), v0, t);
424387

425-
let dtor_ty = ty::mk_ctor_fn(bcx.tcx(),
426-
class_did,
427-
&[get_drop_glue_type(bcx.ccx(), t)],
428-
ty::mk_nil(bcx.tcx()));
429-
let (_, variant_cx) = invoke(variant_cx, dtor_addr, &[self_arg], dtor_ty, DebugLoc::None);
388+
let glue_type = get_drop_glue_type(bcx.ccx(), t);
389+
let dtor_ty = ty::mk_ctor_fn(bcx.tcx(), class_did, &[glue_type], ty::mk_nil(bcx.tcx()));
390+
let (_, bcx) = invoke(bcx, dtor_addr, &[v0], dtor_ty, DebugLoc::None);
430391

431-
variant_cx.fcx.pop_and_trans_custom_cleanup_scope(variant_cx, field_scope)
432-
})
392+
bcx.fcx.pop_and_trans_custom_cleanup_scope(bcx, contents_scope)
433393
}
434394

435395
fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, info: ValueRef)

0 commit comments

Comments
 (0)