Auto merge of #85020 - lrh2000:named-upvars, r=tmandry
Name the captured upvars for closures/generators in debuginfo Previously, debuggers print closures as something like ``` y::main::closure-0 (0x7fffffffdd34) ``` The pointer actually references to an upvar. It is not very obvious, especially for beginners. It's because upvars don't have names before, as they are packed into a tuple. This PR names the upvars, so we can expect to see something like ``` y::main::closure-0 {_captured_ref__b: 0x[...]} ``` r? `@tmandry` Discussed at https://github.com/rust-lang/rust/pull/84752#issuecomment-831639489 .
This commit is contained in:
commit
99efc51dae
9 changed files with 276 additions and 23 deletions
|
@ -1280,6 +1280,31 @@ fn prepare_struct_metadata(
|
|||
// Tuples
|
||||
//=-----------------------------------------------------------------------------
|
||||
|
||||
/// Returns names of captured upvars for closures and generators.
|
||||
///
|
||||
/// Here are some examples:
|
||||
/// - `name__field1__field2` when the upvar is captured by value.
|
||||
/// - `_ref__name__field` when the upvar is captured by reference.
|
||||
fn closure_saved_names_of_captured_variables(tcx: TyCtxt<'tcx>, def_id: DefId) -> Vec<String> {
|
||||
let body = tcx.optimized_mir(def_id);
|
||||
|
||||
body.var_debug_info
|
||||
.iter()
|
||||
.filter_map(|var| {
|
||||
let is_ref = match var.value {
|
||||
mir::VarDebugInfoContents::Place(place) if place.local == mir::Local::new(1) => {
|
||||
// The projection is either `[.., Field, Deref]` or `[.., Field]`. It
|
||||
// implies whether the variable is captured by value or by reference.
|
||||
matches!(place.projection.last().unwrap(), mir::ProjectionElem::Deref)
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
let prefix = if is_ref { "_ref__" } else { "" };
|
||||
Some(prefix.to_owned() + &var.name.as_str())
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
/// Creates `MemberDescription`s for the fields of a tuple.
|
||||
struct TupleMemberDescriptionFactory<'tcx> {
|
||||
ty: Ty<'tcx>,
|
||||
|
@ -1289,14 +1314,25 @@ struct TupleMemberDescriptionFactory<'tcx> {
|
|||
|
||||
impl<'tcx> TupleMemberDescriptionFactory<'tcx> {
|
||||
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> {
|
||||
let mut capture_names = match *self.ty.kind() {
|
||||
ty::Generator(def_id, ..) | ty::Closure(def_id, ..) => {
|
||||
Some(closure_saved_names_of_captured_variables(cx.tcx, def_id).into_iter())
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
let layout = cx.layout_of(self.ty);
|
||||
self.component_types
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, &component_type)| {
|
||||
let (size, align) = cx.size_and_align_of(component_type);
|
||||
let name = if let Some(names) = capture_names.as_mut() {
|
||||
names.next().unwrap()
|
||||
} else {
|
||||
format!("__{}", i)
|
||||
};
|
||||
MemberDescription {
|
||||
name: format!("__{}", i),
|
||||
name,
|
||||
type_metadata: type_metadata(cx, component_type, self.span),
|
||||
offset: layout.fields.offset(i),
|
||||
size,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue