1
Fork 0

Store names of captured variables in optimized_mir

- Closures in external crates may get compiled in because of
  monomorphization. We should store names of captured variables
  in `optimized_mir`, so that they are written into the metadata
  file and we can use them to generate debuginfo.

- If there are breakpoints inside closures, the names of captured
  variables stored in `optimized_mir` can be used to print them.
  Now the name is more precise when disjoint fields are captured.
This commit is contained in:
lrh2000 2021-05-15 19:01:13 +08:00
parent 29856acffe
commit cda90f5541
7 changed files with 132 additions and 66 deletions

View file

@ -3,10 +3,12 @@ use crate::hir::place::{
};
use crate::{mir, ty};
use std::fmt::Write;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_span::Span;
use rustc_span::{Span, Symbol};
use super::{Ty, TyCtxt};
@ -159,37 +161,26 @@ 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__",
};
/// Returns a symbol of the captured upvar, which looks like `name__field1__field2`.
pub fn to_symbol(&self, tcx: TyCtxt<'tcx>) -> Symbol {
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 symbol = tcx.hir().name(hir_id).as_str().to_string();
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::Tuple(_) => write!(&mut symbol, "__{}", idx).unwrap(),
ty::Adt(def, ..) => {
fields = format!(
"{}__{}",
fields,
write!(
&mut symbol,
"__{}",
def.variants[variant].fields[idx as usize].ident.name.as_str(),
);
)
.unwrap();
}
ty => {
bug!("Unexpected type {:?} for `Field` projection", ty)
@ -204,7 +195,7 @@ impl CapturedPlace<'tcx> {
ty = proj.ty;
}
prefix.to_owned() + &name.to_string() + &fields
Symbol::intern(&symbol)
}
/// Returns the hir-id of the root variable for the captured place.