|
71 | 71 |
|
72 | 72 | use rustc_data_structures::unord::UnordMap; |
73 | 73 | use rustc_hir as hir; |
74 | | -use rustc_middle::hir::place::{PlaceBase, Projection, ProjectionKind}; |
| 74 | +use rustc_middle::hir::place::{Projection, ProjectionKind}; |
75 | 75 | use rustc_middle::mir::visit::MutVisitor; |
76 | 76 | use rustc_middle::mir::{self, dump_mir, MirPass}; |
77 | 77 | use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt, TypeVisitableExt}; |
@@ -124,44 +124,10 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody { |
124 | 124 | .tuple_fields() |
125 | 125 | .len(); |
126 | 126 |
|
127 | | - let mut field_remapping = UnordMap::default(); |
128 | | - |
129 | | - let mut child_captures = tcx |
130 | | - .closure_captures(coroutine_def_id) |
131 | | - .iter() |
132 | | - .copied() |
133 | | - // By construction we capture all the args first. |
134 | | - .skip(num_args) |
135 | | - .enumerate() |
136 | | - .peekable(); |
137 | | - |
138 | | - // One parent capture may correspond to several child captures if we end up |
139 | | - // refining the set of captures via edition-2021 precise captures. We want to |
140 | | - // match up any number of child captures with one parent capture, so we keep |
141 | | - // peeking off this `Peekable` until the child doesn't match anymore. |
142 | | - for (parent_field_idx, parent_capture) in |
143 | | - tcx.closure_captures(parent_def_id).iter().copied().enumerate() |
144 | | - { |
145 | | - // Make sure we use every field at least once, b/c why are we capturing something |
146 | | - // if it's not used in the inner coroutine. |
147 | | - let mut field_used_at_least_once = false; |
148 | | - |
149 | | - // A parent matches a child if they share the same prefix of projections. |
150 | | - // The child may have more, if it is capturing sub-fields out of |
151 | | - // something that is captured by-move in the parent closure. |
152 | | - while child_captures.peek().map_or(false, |(_, child_capture)| { |
153 | | - child_prefix_matches_parent_projections(parent_capture, child_capture) |
154 | | - }) { |
155 | | - let (child_field_idx, child_capture) = child_captures.next().unwrap(); |
156 | | - |
157 | | - // This analysis only makes sense if the parent capture is a |
158 | | - // prefix of the child capture. |
159 | | - assert!( |
160 | | - child_capture.place.projections.len() >= parent_capture.place.projections.len(), |
161 | | - "parent capture ({parent_capture:#?}) expected to be prefix of \ |
162 | | - child capture ({child_capture:#?})" |
163 | | - ); |
164 | | - |
| 127 | + let field_remapping: UnordMap<_, _> = ty::analyze_coroutine_closure_captures( |
| 128 | + tcx.closure_captures(parent_def_id).iter().copied(), |
| 129 | + tcx.closure_captures(coroutine_def_id).iter().skip(num_args).copied(), |
| 130 | + |(parent_field_idx, parent_capture), (child_field_idx, child_capture)| { |
165 | 131 | // Store this set of additional projections (fields and derefs). |
166 | 132 | // We need to re-apply them later. |
167 | 133 | let child_precise_captures = |
@@ -192,26 +158,18 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody { |
192 | 158 | ), |
193 | 159 | }; |
194 | 160 |
|
195 | | - field_remapping.insert( |
| 161 | + ( |
196 | 162 | FieldIdx::from_usize(child_field_idx + num_args), |
197 | 163 | ( |
198 | 164 | FieldIdx::from_usize(parent_field_idx + num_args), |
199 | 165 | parent_capture_ty, |
200 | 166 | needs_deref, |
201 | 167 | child_precise_captures, |
202 | 168 | ), |
203 | | - ); |
204 | | - |
205 | | - field_used_at_least_once = true; |
206 | | - } |
207 | | - |
208 | | - // Make sure the field was used at least once. |
209 | | - assert!( |
210 | | - field_used_at_least_once, |
211 | | - "we captured {parent_capture:#?} but it was not used in the child coroutine?" |
212 | | - ); |
213 | | - } |
214 | | - assert_eq!(child_captures.next(), None, "leftover child captures?"); |
| 169 | + ) |
| 170 | + }, |
| 171 | + ) |
| 172 | + .collect(); |
215 | 173 |
|
216 | 174 | if coroutine_kind == ty::ClosureKind::FnOnce { |
217 | 175 | assert_eq!(field_remapping.len(), tcx.closure_captures(parent_def_id).len()); |
@@ -241,22 +199,6 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody { |
241 | 199 | } |
242 | 200 | } |
243 | 201 |
|
244 | | -fn child_prefix_matches_parent_projections( |
245 | | - parent_capture: &ty::CapturedPlace<'_>, |
246 | | - child_capture: &ty::CapturedPlace<'_>, |
247 | | -) -> bool { |
248 | | - let PlaceBase::Upvar(parent_base) = parent_capture.place.base else { |
249 | | - bug!("expected capture to be an upvar"); |
250 | | - }; |
251 | | - let PlaceBase::Upvar(child_base) = child_capture.place.base else { |
252 | | - bug!("expected capture to be an upvar"); |
253 | | - }; |
254 | | - |
255 | | - parent_base.var_path.hir_id == child_base.var_path.hir_id |
256 | | - && std::iter::zip(&child_capture.place.projections, &parent_capture.place.projections) |
257 | | - .all(|(child, parent)| child.kind == parent.kind) |
258 | | -} |
259 | | - |
260 | 202 | struct MakeByMoveBody<'tcx> { |
261 | 203 | tcx: TyCtxt<'tcx>, |
262 | 204 | field_remapping: UnordMap<FieldIdx, (FieldIdx, Ty<'tcx>, bool, &'tcx [Projection<'tcx>])>, |
|
0 commit comments