Skip to content

Commit 9bf3022

Browse files
Rollup merge of rust-lang#112759 - cjgillot:closure-names, r=oli-obk
Make closure_saved_names_of_captured_variables a query. As we will start removing debuginfo during MIR optimizations, we need to keep them somewhere.
2 parents 356ee33 + 689607e commit 9bf3022

File tree

17 files changed

+100
-102
lines changed

17 files changed

+100
-102
lines changed

compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1031,7 +1031,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>(
10311031
build_field_di_node(
10321032
cx,
10331033
closure_or_generator_di_node,
1034-
capture_name,
1034+
capture_name.as_str(),
10351035
cx.size_and_align_of(up_var_ty),
10361036
layout.fields.offset(index),
10371037
DIFlags::FlagZero,

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -676,8 +676,7 @@ fn build_union_fields_for_direct_tag_generator<'ll, 'tcx>(
676676
_ => unreachable!(),
677677
};
678678

679-
let (generator_layout, state_specific_upvar_names) =
680-
cx.tcx.generator_layout_and_saved_local_names(generator_def_id);
679+
let generator_layout = cx.tcx.optimized_mir(generator_def_id).generator_layout().unwrap();
681680

682681
let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(generator_def_id);
683682
let variant_range = generator_substs.variant_range(generator_def_id, cx.tcx);
@@ -714,7 +713,6 @@ fn build_union_fields_for_direct_tag_generator<'ll, 'tcx>(
714713
generator_type_and_layout,
715714
generator_type_di_node,
716715
generator_layout,
717-
&state_specific_upvar_names,
718716
&common_upvar_names,
719717
);
720718

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_hir::def::CtorKind;
66
use rustc_index::IndexSlice;
77
use rustc_middle::{
88
bug,
9-
mir::{GeneratorLayout, GeneratorSavedLocal},
9+
mir::GeneratorLayout,
1010
ty::{
1111
self,
1212
layout::{IntegerExt, LayoutOf, PrimitiveExt, TyAndLayout},
@@ -323,8 +323,7 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>(
323323
generator_type_and_layout: TyAndLayout<'tcx>,
324324
generator_type_di_node: &'ll DIType,
325325
generator_layout: &GeneratorLayout<'tcx>,
326-
state_specific_upvar_names: &IndexSlice<GeneratorSavedLocal, Option<Symbol>>,
327-
common_upvar_names: &[String],
326+
common_upvar_names: &IndexSlice<FieldIdx, Symbol>,
328327
) -> &'ll DIType {
329328
let variant_name = GeneratorSubsts::variant_name(variant_index);
330329
let unique_type_id = UniqueTypeId::for_enum_variant_struct_type(
@@ -357,7 +356,7 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>(
357356
.map(|field_index| {
358357
let generator_saved_local = generator_layout.variant_fields[variant_index]
359358
[FieldIdx::from_usize(field_index)];
360-
let field_name_maybe = state_specific_upvar_names[generator_saved_local];
359+
let field_name_maybe = generator_layout.field_names[generator_saved_local];
361360
let field_name = field_name_maybe
362361
.as_ref()
363362
.map(|s| Cow::from(s.as_str()))
@@ -380,12 +379,13 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>(
380379
// Fields that are common to all states
381380
let common_fields: SmallVec<_> = generator_substs
382381
.prefix_tys()
382+
.zip(common_upvar_names)
383383
.enumerate()
384-
.map(|(index, upvar_ty)| {
384+
.map(|(index, (upvar_ty, upvar_name))| {
385385
build_field_di_node(
386386
cx,
387387
variant_struct_type_di_node,
388-
&common_upvar_names[index],
388+
upvar_name.as_str(),
389389
cx.size_and_align_of(upvar_ty),
390390
generator_type_and_layout.fields.offset(index),
391391
DIFlags::FlagZero,

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ pub(super) fn build_generator_di_node<'ll, 'tcx>(
155155
DIFlags::FlagZero,
156156
),
157157
|cx, generator_type_di_node| {
158-
let (generator_layout, state_specific_upvar_names) =
159-
cx.tcx.generator_layout_and_saved_local_names(generator_def_id);
158+
let generator_layout =
159+
cx.tcx.optimized_mir(generator_def_id).generator_layout().unwrap();
160160

161161
let Variants::Multiple { tag_encoding: TagEncoding::Direct, ref variants, .. } = generator_type_and_layout.variants else {
162162
bug!(
@@ -195,7 +195,6 @@ pub(super) fn build_generator_di_node<'ll, 'tcx>(
195195
generator_type_and_layout,
196196
generator_type_di_node,
197197
generator_layout,
198-
&state_specific_upvar_names,
199198
&common_upvar_names,
200199
),
201200
source_info,

compiler/rustc_data_structures/src/stable_hasher.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::sip128::SipHasher128;
22
use rustc_index::bit_set::{self, BitSet};
3-
use rustc_index::{Idx, IndexVec};
3+
use rustc_index::{Idx, IndexSlice, IndexVec};
44
use smallvec::SmallVec;
55
use std::fmt;
66
use std::hash::{BuildHasher, Hash, Hasher};
@@ -597,6 +597,18 @@ where
597597
}
598598
}
599599

600+
impl<I: Idx, T, CTX> HashStable<CTX> for IndexSlice<I, T>
601+
where
602+
T: HashStable<CTX>,
603+
{
604+
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
605+
self.len().hash_stable(ctx, hasher);
606+
for v in &self.raw {
607+
v.hash_stable(ctx, hasher);
608+
}
609+
}
610+
}
611+
600612
impl<I: Idx, T, CTX> HashStable<CTX> for IndexVec<I, T>
601613
where
602614
T: HashStable<CTX>,

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+1
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ provide! { tcx, def_id, other, cdata,
218218
thir_abstract_const => { table }
219219
optimized_mir => { table }
220220
mir_for_ctfe => { table }
221+
closure_saved_names_of_captured_variables => { table }
221222
mir_generator_witnesses => { table }
222223
promoted_mir => { table }
223224
def_span => { table }

compiler/rustc_metadata/src/rmeta/encoder.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1520,6 +1520,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
15201520
debug!("EntryBuilder::encode_mir({:?})", def_id);
15211521
if encode_opt {
15221522
record!(self.tables.optimized_mir[def_id.to_def_id()] <- tcx.optimized_mir(def_id));
1523+
record!(self.tables.closure_saved_names_of_captured_variables[def_id.to_def_id()]
1524+
<- tcx.closure_saved_names_of_captured_variables(def_id));
15231525

15241526
if tcx.sess.opts.unstable_opts.drop_tracking_mir
15251527
&& let DefKind::Generator = self.tcx.def_kind(def_id)

compiler/rustc_metadata/src/rmeta/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use rustc_span::edition::Edition;
3232
use rustc_span::hygiene::{ExpnIndex, MacroKind};
3333
use rustc_span::symbol::{Ident, Symbol};
3434
use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Span};
35-
use rustc_target::abi::VariantIdx;
35+
use rustc_target::abi::{FieldIdx, VariantIdx};
3636
use rustc_target::spec::{PanicStrategy, TargetTriple};
3737

3838
use std::marker::PhantomData;
@@ -416,6 +416,7 @@ define_tables! {
416416
object_lifetime_default: Table<DefIndex, LazyValue<ObjectLifetimeDefault>>,
417417
optimized_mir: Table<DefIndex, LazyValue<mir::Body<'static>>>,
418418
mir_for_ctfe: Table<DefIndex, LazyValue<mir::Body<'static>>>,
419+
closure_saved_names_of_captured_variables: Table<DefIndex, LazyValue<IndexVec<FieldIdx, Symbol>>>,
419420
mir_generator_witnesses: Table<DefIndex, LazyValue<mir::GeneratorLayout<'static>>>,
420421
promoted_mir: Table<DefIndex, LazyValue<IndexVec<mir::Promoted, mir::Body<'static>>>>,
421422
thir_abstract_const: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::Const<'static>>>>,

compiler/rustc_middle/src/arena.rs

+5
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ macro_rules! arena_types {
2727
rustc_middle::mir::Promoted,
2828
rustc_middle::mir::Body<'tcx>
2929
>,
30+
[decode] closure_debuginfo:
31+
rustc_index::IndexVec<
32+
rustc_target::abi::FieldIdx,
33+
rustc_span::symbol::Symbol,
34+
>,
3035
[decode] typeck_results: rustc_middle::ty::TypeckResults<'tcx>,
3136
[decode] borrowck_result:
3237
rustc_middle::mir::BorrowCheckResult<'tcx>,

compiler/rustc_middle/src/mir/query.rs

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use rustc_hir as hir;
99
use rustc_hir::def_id::LocalDefId;
1010
use rustc_index::bit_set::BitMatrix;
1111
use rustc_index::{Idx, IndexVec};
12+
use rustc_span::symbol::Symbol;
1213
use rustc_span::Span;
1314
use rustc_target::abi::{FieldIdx, VariantIdx};
1415
use smallvec::SmallVec;
@@ -150,6 +151,9 @@ pub struct GeneratorLayout<'tcx> {
150151
/// The type of every local stored inside the generator.
151152
pub field_tys: IndexVec<GeneratorSavedLocal, GeneratorSavedTy<'tcx>>,
152153

154+
/// The name for debuginfo.
155+
pub field_names: IndexVec<GeneratorSavedLocal, Option<Symbol>>,
156+
153157
/// Which of the above fields are in each variant. Note that one field may
154158
/// be stored in multiple variants.
155159
pub variant_fields: IndexVec<VariantIdx, IndexVec<FieldIdx, GeneratorSavedLocal>>,

compiler/rustc_middle/src/query/erase.rs

+4
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ impl<T> EraseType for &'_ ty::List<T> {
5555
type Result = [u8; size_of::<*const ()>()];
5656
}
5757

58+
impl<I: rustc_index::Idx, T> EraseType for &'_ rustc_index::IndexSlice<I, T> {
59+
type Result = [u8; size_of::<&'static rustc_index::IndexSlice<u32, ()>>()];
60+
}
61+
5862
impl<T> EraseType for Result<&'_ T, traits::query::NoSolution> {
5963
type Result = [u8; size_of::<Result<&'static (), traits::query::NoSolution>>()];
6064
}

compiler/rustc_middle/src/query/mod.rs

+13
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,19 @@ rustc_queries! {
531531
}
532532
}
533533

534+
/// Returns names of captured upvars for closures and generators.
535+
///
536+
/// Here are some examples:
537+
/// - `name__field1__field2` when the upvar is captured by value.
538+
/// - `_ref__name__field` when the upvar is captured by reference.
539+
///
540+
/// For generators this only contains upvars that are shared by all states.
541+
query closure_saved_names_of_captured_variables(def_id: DefId) -> &'tcx IndexVec<abi::FieldIdx, Symbol> {
542+
arena_cache
543+
desc { |tcx| "computing debuginfo for closure `{}`", tcx.def_path_str(def_id) }
544+
separate_provide_extern
545+
}
546+
534547
query mir_generator_witnesses(key: DefId) -> &'tcx Option<mir::GeneratorLayout<'tcx>> {
535548
arena_cache
536549
desc { |tcx| "generator witness types for `{}`", tcx.def_path_str(key) }

compiler/rustc_middle/src/ty/util.rs

-76
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! Miscellaneous type-system utilities that are too small to deserve their own modules.
22
33
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
4-
use crate::mir;
54
use crate::query::Providers;
65
use crate::ty::layout::IntegerExt;
76
use crate::ty::{
@@ -17,7 +16,6 @@ use rustc_hir as hir;
1716
use rustc_hir::def::{CtorOf, DefKind, Res};
1817
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
1918
use rustc_index::bit_set::GrowableBitSet;
20-
use rustc_index::{Idx, IndexVec};
2119
use rustc_macros::HashStable;
2220
use rustc_session::Limit;
2321
use rustc_span::sym;
@@ -738,80 +736,6 @@ impl<'tcx> TyCtxt<'tcx> {
738736
if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) }
739737
}
740738

741-
/// Returns names of captured upvars for closures and generators.
742-
///
743-
/// Here are some examples:
744-
/// - `name__field1__field2` when the upvar is captured by value.
745-
/// - `_ref__name__field` when the upvar is captured by reference.
746-
///
747-
/// For generators this only contains upvars that are shared by all states.
748-
pub fn closure_saved_names_of_captured_variables(
749-
self,
750-
def_id: DefId,
751-
) -> SmallVec<[String; 16]> {
752-
let body = self.optimized_mir(def_id);
753-
754-
body.var_debug_info
755-
.iter()
756-
.filter_map(|var| {
757-
let is_ref = match var.value {
758-
mir::VarDebugInfoContents::Place(place)
759-
if place.local == mir::Local::new(1) =>
760-
{
761-
// The projection is either `[.., Field, Deref]` or `[.., Field]`. It
762-
// implies whether the variable is captured by value or by reference.
763-
matches!(place.projection.last().unwrap(), mir::ProjectionElem::Deref)
764-
}
765-
_ => return None,
766-
};
767-
let prefix = if is_ref { "_ref__" } else { "" };
768-
Some(prefix.to_owned() + var.name.as_str())
769-
})
770-
.collect()
771-
}
772-
773-
// FIXME(eddyb) maybe precompute this? Right now it's computed once
774-
// per generator monomorphization, but it doesn't depend on substs.
775-
pub fn generator_layout_and_saved_local_names(
776-
self,
777-
def_id: DefId,
778-
) -> (
779-
&'tcx ty::GeneratorLayout<'tcx>,
780-
IndexVec<mir::GeneratorSavedLocal, Option<rustc_span::Symbol>>,
781-
) {
782-
let tcx = self;
783-
let body = tcx.optimized_mir(def_id);
784-
let generator_layout = body.generator_layout().unwrap();
785-
let mut generator_saved_local_names =
786-
IndexVec::from_elem(None, &generator_layout.field_tys);
787-
788-
let state_arg = mir::Local::new(1);
789-
for var in &body.var_debug_info {
790-
let mir::VarDebugInfoContents::Place(place) = &var.value else { continue };
791-
if place.local != state_arg {
792-
continue;
793-
}
794-
match place.projection[..] {
795-
[
796-
// Deref of the `Pin<&mut Self>` state argument.
797-
mir::ProjectionElem::Field(..),
798-
mir::ProjectionElem::Deref,
799-
// Field of a variant of the state.
800-
mir::ProjectionElem::Downcast(_, variant),
801-
mir::ProjectionElem::Field(field, _),
802-
] => {
803-
let name = &mut generator_saved_local_names
804-
[generator_layout.variant_fields[variant][field]];
805-
if name.is_none() {
806-
name.replace(var.name);
807-
}
808-
}
809-
_ => {}
810-
}
811-
}
812-
(generator_layout, generator_saved_local_names)
813-
}
814-
815739
/// Query and get an English description for the item's kind.
816740
pub fn def_descr(self, def_id: DefId) -> &'static str {
817741
self.def_kind_descr(self.def_kind(def_id), def_id)

compiler/rustc_mir_build/src/build/mod.rs

+16
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,22 @@ pub(crate) fn mir_built(
3636
tcx.alloc_steal_mir(mir_build(tcx, def))
3737
}
3838

39+
pub(crate) fn closure_saved_names_of_captured_variables<'tcx>(
40+
tcx: TyCtxt<'tcx>,
41+
def_id: LocalDefId,
42+
) -> IndexVec<FieldIdx, Symbol> {
43+
tcx.closure_captures(def_id)
44+
.iter()
45+
.map(|captured_place| {
46+
let name = captured_place.to_symbol();
47+
match captured_place.info.capture_kind {
48+
ty::UpvarCapture::ByValue => name,
49+
ty::UpvarCapture::ByRef(..) => Symbol::intern(&format!("_ref__{name}")),
50+
}
51+
})
52+
.collect()
53+
}
54+
3955
/// Construct the MIR for a given `DefId`.
4056
fn mir_build(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
4157
// Ensure unsafeck and abstract const building is ran before we steal the THIR.

compiler/rustc_mir_build/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ pub fn provide(providers: &mut Providers) {
3333
providers.check_match = thir::pattern::check_match;
3434
providers.lit_to_const = thir::constant::lit_to_const;
3535
providers.mir_built = build::mir_built;
36+
providers.closure_saved_names_of_captured_variables =
37+
build::closure_saved_names_of_captured_variables;
3638
providers.thir_check_unsafety = check_unsafety::thir_check_unsafety;
3739
providers.thir_body = thir::cx::thir_body;
3840
providers.thir_tree = thir::print::thir_tree;

0 commit comments

Comments
 (0)