1
Fork 0

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 commit names the upvars,
so we can expect to see something like
```
y::main::closure-0 {_captured_ref__b: 0x[...]}
```
This commit is contained in:
lrh2000 2021-05-05 23:50:44 +08:00
parent 95fb131521
commit 29856acffe
5 changed files with 165 additions and 8 deletions

View file

@ -159,6 +159,54 @@ impl CapturedPlace<'tcx> {
place_to_string_for_capture(tcx, &self.place)
}
/// Returns mangled names of captured upvars. Here are some examples:
/// - `_captured_val__name__field`
/// - `_captured_ref__name__field`
///
/// The purpose is to use those names in debuginfo. They should be human-understandable.
/// Without the names, the end users may get confused when the debuggers just print some
/// pointers in closures or generators.
pub fn to_mangled_name(&self, tcx: TyCtxt<'tcx>) -> String {
let prefix = match self.info.capture_kind {
ty::UpvarCapture::ByValue(_) => "_captured_val__",
ty::UpvarCapture::ByRef(_) => "_captured_ref__",
};
let hir_id = match self.place.base {
HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
base => bug!("Expected an upvar, found {:?}", base),
};
let name = tcx.hir().name(hir_id);
let mut ty = self.place.base_ty;
let mut fields = String::new();
for proj in self.place.projections.iter() {
match proj.kind {
HirProjectionKind::Field(idx, variant) => match ty.kind() {
ty::Tuple(_) => fields = format!("{}__{}", fields, idx),
ty::Adt(def, ..) => {
fields = format!(
"{}__{}",
fields,
def.variants[variant].fields[idx as usize].ident.name.as_str(),
);
}
ty => {
bug!("Unexpected type {:?} for `Field` projection", ty)
}
},
// Ignore derefs for now, as they are likely caused by
// autoderefs that don't appear in the original code.
HirProjectionKind::Deref => {}
proj => bug!("Unexpected projection {:?} in captured place", proj),
}
ty = proj.ty;
}
prefix.to_owned() + &name.to_string() + &fields
}
/// Returns the hir-id of the root variable for the captured place.
/// e.g., if `a.b.c` was captured, would return the hir-id for `a`.
pub fn get_root_variable(&self) -> hir::HirId {