@@ -167,59 +167,54 @@ fn find_capture_matching_projections<'a, 'tcx>(
167
167
} )
168
168
}
169
169
170
- /// Takes a PlaceBuilder and resolves the upvar (if any) within it, so that the
171
- /// `PlaceBuilder` now starts from `PlaceBase::Local`.
172
- ///
173
- /// Returns a Result with the error being the PlaceBuilder (`from_builder`) that was not found.
170
+ /// Takes an upvar place and tries to resolve it into a `PlaceBuilder`
171
+ /// with `PlaceBase::Local`
174
172
#[ instrument( level = "trace" , skip( cx) , ret) ]
175
173
fn to_upvars_resolved_place_builder < ' tcx > (
176
- from_builder : PlaceBuilder < ' tcx > ,
177
174
cx : & Builder < ' _ , ' tcx > ,
178
- ) -> Result < PlaceBuilder < ' tcx > , PlaceBuilder < ' tcx > > {
179
- match from_builder . base {
180
- PlaceBase :: Local ( _ ) => Ok ( from_builder ) ,
181
- PlaceBase :: Upvar { var_hir_id , closure_def_id } = > {
182
- let Some ( ( capture_index, capture) ) =
183
- find_capture_matching_projections (
184
- & cx. upvars ,
185
- var_hir_id,
186
- & from_builder . projection ,
187
- ) else {
188
- let closure_span = cx. tcx . def_span ( closure_def_id) ;
189
- if !enable_precise_capture ( cx. tcx , closure_span) {
190
- bug ! (
191
- "No associated capture found for {:?}[{:#?}] even though \
192
- capture_disjoint_fields isn't enabled",
193
- var_hir_id,
194
- from_builder . projection
195
- )
196
- } else {
197
- debug ! (
198
- "No associated capture found for {:?}[{:#?}]" ,
199
- var_hir_id, from_builder . projection,
200
- ) ;
201
- }
202
- return Err ( from_builder ) ;
203
- } ;
175
+ var_hir_id : LocalVarId ,
176
+ closure_def_id : LocalDefId ,
177
+ projection : & [ PlaceElem < ' tcx > ] ,
178
+ ) -> Option < PlaceBuilder < ' tcx > > {
179
+ let Some ( ( capture_index, capture) ) =
180
+ find_capture_matching_projections (
181
+ & cx. upvars ,
182
+ var_hir_id,
183
+ & projection,
184
+ ) else {
185
+ let closure_span = cx. tcx . def_span ( closure_def_id) ;
186
+ if !enable_precise_capture ( cx. tcx , closure_span) {
187
+ bug ! (
188
+ "No associated capture found for {:?}[{:#?}] even though \
189
+ capture_disjoint_fields isn't enabled",
190
+ var_hir_id,
191
+ projection
192
+ )
193
+ } else {
194
+ debug ! (
195
+ "No associated capture found for {:?}[{:#?}]" ,
196
+ var_hir_id, projection,
197
+ ) ;
198
+ }
199
+ return None ;
200
+ } ;
204
201
205
- // Access the capture by accessing the field within the Closure struct.
206
- let capture_info = & cx. upvars [ capture_index] ;
202
+ // Access the capture by accessing the field within the Closure struct.
203
+ let capture_info = & cx. upvars [ capture_index] ;
207
204
208
- let mut upvar_resolved_place_builder = PlaceBuilder :: from ( capture_info. use_place ) ;
205
+ let mut upvar_resolved_place_builder = PlaceBuilder :: from ( capture_info. use_place ) ;
209
206
210
- // We used some of the projections to build the capture itself,
211
- // now we apply the remaining to the upvar resolved place.
212
- trace ! ( ?capture. captured_place, ?from_builder . projection) ;
213
- let remaining_projections = strip_prefix (
214
- capture. captured_place . place . base_ty ,
215
- from_builder . projection ,
216
- & capture. captured_place . place . projections ,
217
- ) ;
218
- upvar_resolved_place_builder. projection . extend ( remaining_projections) ;
207
+ // We used some of the projections to build the capture itself,
208
+ // now we apply the remaining to the upvar resolved place.
209
+ trace ! ( ?capture. captured_place, ?projection) ;
210
+ let remaining_projections = strip_prefix (
211
+ capture. captured_place . place . base_ty ,
212
+ projection,
213
+ & capture. captured_place . place . projections ,
214
+ ) ;
215
+ upvar_resolved_place_builder. projection . extend ( remaining_projections) ;
219
216
220
- Ok ( upvar_resolved_place_builder)
221
- }
222
- }
217
+ Some ( upvar_resolved_place_builder)
223
218
}
224
219
225
220
/// Returns projections remaining after stripping an initial prefix of HIR
@@ -228,13 +223,14 @@ fn to_upvars_resolved_place_builder<'tcx>(
228
223
/// Supports only HIR projection kinds that represent a path that might be
229
224
/// captured by a closure or a generator, i.e., an `Index` or a `Subslice`
230
225
/// projection kinds are unsupported.
231
- fn strip_prefix < ' tcx > (
226
+ fn strip_prefix < ' a , ' tcx > (
232
227
mut base_ty : Ty < ' tcx > ,
233
- projections : Vec < PlaceElem < ' tcx > > ,
228
+ projections : & ' a [ PlaceElem < ' tcx > ] ,
234
229
prefix_projections : & [ HirProjection < ' tcx > ] ,
235
- ) -> impl Iterator < Item = PlaceElem < ' tcx > > {
230
+ ) -> impl Iterator < Item = PlaceElem < ' tcx > > + ' a {
236
231
let mut iter = projections
237
- . into_iter ( )
232
+ . iter ( )
233
+ . copied ( )
238
234
// Filter out opaque casts, they are unnecessary in the prefix.
239
235
. filter ( |elem| !matches ! ( elem, ProjectionElem :: OpaqueCast ( ..) ) ) ;
240
236
for projection in prefix_projections {
@@ -258,21 +254,31 @@ fn strip_prefix<'tcx>(
258
254
}
259
255
260
256
impl < ' tcx > PlaceBuilder < ' tcx > {
261
- pub ( in crate :: build) fn into_place ( self , cx : & Builder < ' _ , ' tcx > ) -> Place < ' tcx > {
262
- if let PlaceBase :: Local ( local) = self . base {
263
- Place { local, projection : cx. tcx . intern_place_elems ( & self . projection ) }
264
- } else {
265
- self . expect_upvars_resolved ( cx) . into_place ( cx)
266
- }
257
+ pub ( in crate :: build) fn into_place ( mut self , cx : & Builder < ' _ , ' tcx > ) -> Place < ' tcx > {
258
+ self = self . resolve_upvar ( cx) . unwrap_or ( self ) ;
259
+ let PlaceBase :: Local ( local) = self . base else { panic ! ( "expected local" ) } ;
260
+ Place { local, projection : cx. tcx . intern_place_elems ( & self . projection ) }
267
261
}
268
262
269
263
fn expect_upvars_resolved ( self , cx : & Builder < ' _ , ' tcx > ) -> PlaceBuilder < ' tcx > {
270
- to_upvars_resolved_place_builder ( self , cx) . unwrap ( )
264
+ match self . base {
265
+ PlaceBase :: Local ( _) => self ,
266
+ PlaceBase :: Upvar { ..} => self . resolve_upvar ( cx) . unwrap ( ) ,
267
+ }
268
+ }
269
+
270
+ pub ( in crate :: build) fn try_upvars_resolved (
271
+ self ,
272
+ cx : & Builder < ' _ , ' tcx > ,
273
+ ) -> Result < PlaceBuilder < ' tcx > , PlaceBuilder < ' tcx > > {
274
+ match self . base {
275
+ PlaceBase :: Local ( _) => Ok ( self ) ,
276
+ PlaceBase :: Upvar { .. } => self . resolve_upvar ( cx) . ok_or ( self ) ,
277
+ }
271
278
}
272
279
273
280
/// Attempts to resolve the `PlaceBuilder`.
274
- /// On success, it will return the resolved `PlaceBuilder`.
275
- /// On failure, it will return itself.
281
+ /// Returns `None` if this is not an upvar.
276
282
///
277
283
/// Upvars resolve may fail for a `PlaceBuilder` when attempting to
278
284
/// resolve a disjoint field whose root variable is not captured
@@ -281,11 +287,14 @@ impl<'tcx> PlaceBuilder<'tcx> {
281
287
/// not captured. This can happen because the final mir that will be
282
288
/// generated doesn't require a read for this place. Failures will only
283
289
/// happen inside closures.
284
- pub ( in crate :: build) fn try_upvars_resolved (
285
- self ,
290
+ pub ( in crate :: build) fn resolve_upvar (
291
+ & self ,
286
292
cx : & Builder < ' _ , ' tcx > ,
287
- ) -> Result < PlaceBuilder < ' tcx > , PlaceBuilder < ' tcx > > {
288
- to_upvars_resolved_place_builder ( self , cx)
293
+ ) -> Option < PlaceBuilder < ' tcx > > {
294
+ let PlaceBase :: Upvar { var_hir_id, closure_def_id } = self . base else {
295
+ return None ;
296
+ } ;
297
+ to_upvars_resolved_place_builder ( cx, var_hir_id, closure_def_id, & self . projection )
289
298
}
290
299
291
300
pub ( crate ) fn base ( & self ) -> PlaceBase {
0 commit comments