Skip to content

Commit ef6bc3b

Browse files
committed
collect collections instead of pushing iteratively in coroutine layout computation
1 parent 6380899 commit ef6bc3b

File tree

1 file changed

+49
-50
lines changed

1 file changed

+49
-50
lines changed

compiler/rustc_mir_transform/src/coroutine.rs

Lines changed: 49 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -982,71 +982,70 @@ fn compute_layout<'tcx>(
982982
} = liveness;
983983

984984
// Gather live local types and their indices.
985-
let mut locals = IndexVec::<CoroutineSavedLocal, _>::new();
986-
let mut tys = IndexVec::<CoroutineSavedLocal, _>::new();
987-
for (saved_local, local) in saved_locals.iter_enumerated() {
988-
debug!("coroutine saved local {:?} => {:?}", saved_local, local);
989-
990-
locals.push(local);
991-
let decl = &body.local_decls[local];
992-
debug!(?decl);
993-
994-
// Do not `unwrap_crate_local` here, as post-borrowck cleanup may have already cleared
995-
// the information. This is alright, since `ignore_for_traits` is only relevant when
996-
// this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer
997-
// default.
998-
let ignore_for_traits = match decl.local_info {
999-
// Do not include raw pointers created from accessing `static` items, as those could
1000-
// well be re-created by another access to the same static.
1001-
ClearCrossCrate::Set(box LocalInfo::StaticRef { is_thread_local, .. }) => {
1002-
!is_thread_local
1003-
}
1004-
// Fake borrows are only read by fake reads, so do not have any reality in
1005-
// post-analysis MIR.
1006-
ClearCrossCrate::Set(box LocalInfo::FakeBorrow) => true,
1007-
_ => false,
1008-
};
1009-
let decl =
1010-
CoroutineSavedTy { ty: decl.ty, source_info: decl.source_info, ignore_for_traits };
1011-
debug!(?decl);
985+
let (locals, tys): (IndexVec<_, _>, IndexVec<_, _>) = saved_locals
986+
.iter_enumerated()
987+
.map(|(saved_local, local)| {
988+
debug!("coroutine saved local {saved_local:?} => {local:?}");
1012989

1013-
tys.push(decl);
1014-
}
990+
let decl = &body.local_decls[local];
991+
debug!(?decl);
992+
993+
// Do not `unwrap_crate_local` here, as post-borrowck cleanup may have already cleared
994+
// the information. This is alright, since `ignore_for_traits` is only relevant when
995+
// this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer
996+
// default.
997+
let ignore_for_traits = match decl.local_info {
998+
// Do not include raw pointers created from accessing `static` items, as those could
999+
// well be re-created by another access to the same static.
1000+
ClearCrossCrate::Set(box LocalInfo::StaticRef { is_thread_local, .. }) => {
1001+
!is_thread_local
1002+
}
1003+
// Fake borrows are only read by fake reads, so do not have any reality in
1004+
// post-analysis MIR.
1005+
ClearCrossCrate::Set(box LocalInfo::FakeBorrow) => true,
1006+
_ => false,
1007+
};
1008+
let decl =
1009+
CoroutineSavedTy { ty: decl.ty, source_info: decl.source_info, ignore_for_traits };
1010+
debug!(?decl);
1011+
1012+
(local, decl)
1013+
})
1014+
.unzip();
10151015

10161016
// Leave empty variants for the UNRESUMED, RETURNED, and POISONED states.
10171017
// In debuginfo, these will correspond to the beginning (UNRESUMED) or end
10181018
// (RETURNED, POISONED) of the function.
10191019
let body_span = body.source_scopes[OUTERMOST_SOURCE_SCOPE].span;
1020-
let mut variant_source_info: IndexVec<VariantIdx, SourceInfo> = [
1020+
let variant_source_info: IndexVec<VariantIdx, SourceInfo> = [
10211021
SourceInfo::outermost(body_span.shrink_to_lo()),
10221022
SourceInfo::outermost(body_span.shrink_to_hi()),
10231023
SourceInfo::outermost(body_span.shrink_to_hi()),
10241024
]
1025-
.iter()
1026-
.copied()
1025+
.into_iter()
1026+
.chain(source_info_at_suspension_points)
10271027
.collect();
10281028

10291029
// Build the coroutine variant field list.
10301030
// Create a map from local indices to coroutine struct indices.
1031-
let mut variant_fields: IndexVec<VariantIdx, IndexVec<FieldIdx, CoroutineSavedLocal>> =
1032-
iter::repeat(IndexVec::new()).take(CoroutineArgs::RESERVED_VARIANTS).collect();
10331031
let mut remap = IndexVec::from_elem_n(None, saved_locals.domain_size());
1034-
for (suspension_point_idx, live_locals) in live_locals_at_suspension_points.iter().enumerate() {
1035-
let variant_index =
1036-
VariantIdx::from(CoroutineArgs::RESERVED_VARIANTS + suspension_point_idx);
1037-
let mut fields = IndexVec::new();
1038-
for (idx, saved_local) in live_locals.iter().enumerate() {
1039-
fields.push(saved_local);
1040-
// Note that if a field is included in multiple variants, we will
1041-
// just use the first one here. That's fine; fields do not move
1042-
// around inside coroutines, so it doesn't matter which variant
1043-
// index we access them by.
1044-
let idx = FieldIdx::from_usize(idx);
1045-
remap[locals[saved_local]] = Some((tys[saved_local].ty, variant_index, idx));
1046-
}
1047-
variant_fields.push(fields);
1048-
variant_source_info.push(source_info_at_suspension_points[suspension_point_idx]);
1049-
}
1032+
let variant_fields = iter::repeat_n(IndexVec::new(), CoroutineArgs::RESERVED_VARIANTS)
1033+
.chain(live_locals_at_suspension_points.into_iter().enumerate().map(
1034+
|(suspension_point_idx, live_locals)| {
1035+
let variant_index =
1036+
VariantIdx::from(CoroutineArgs::RESERVED_VARIANTS + suspension_point_idx);
1037+
let fields = live_locals.iter().collect::<IndexVec<FieldIdx, _>>();
1038+
for (idx, &saved_local) in fields.iter_enumerated() {
1039+
// Note that if a field is included in multiple variants, we will
1040+
// just use the first one here. That's fine; fields do not move
1041+
// around inside coroutines, so it doesn't matter which variant
1042+
// index we access them by.
1043+
remap[locals[saved_local]] = Some((tys[saved_local].ty, variant_index, idx));
1044+
}
1045+
fields
1046+
},
1047+
))
1048+
.collect::<IndexVec<VariantIdx, _>>();
10501049
debug!("coroutine variant_fields = {:?}", variant_fields);
10511050
debug!("coroutine storage_conflicts = {:#?}", storage_conflicts);
10521051

0 commit comments

Comments
 (0)