@@ -167,59 +167,54 @@ fn find_capture_matching_projections<'a, 'tcx>(
167167 } )
168168}
169169
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`
174172#[ instrument( level = "trace" , skip( cx) , ret) ]
175173fn to_upvars_resolved_place_builder < ' tcx > (
176- from_builder : PlaceBuilder < ' tcx > ,
177174 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+ } ;
204201
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] ;
207204
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 ) ;
209206
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) ;
219216
220- Ok ( upvar_resolved_place_builder)
221- }
222- }
217+ Some ( upvar_resolved_place_builder)
223218}
224219
225220/// Returns projections remaining after stripping an initial prefix of HIR
@@ -228,13 +223,14 @@ fn to_upvars_resolved_place_builder<'tcx>(
228223/// Supports only HIR projection kinds that represent a path that might be
229224/// captured by a closure or a generator, i.e., an `Index` or a `Subslice`
230225/// projection kinds are unsupported.
231- fn strip_prefix < ' tcx > (
226+ fn strip_prefix < ' a , ' tcx > (
232227 mut base_ty : Ty < ' tcx > ,
233- projections : Vec < PlaceElem < ' tcx > > ,
228+ projections : & ' a [ PlaceElem < ' tcx > ] ,
234229 prefix_projections : & [ HirProjection < ' tcx > ] ,
235- ) -> impl Iterator < Item = PlaceElem < ' tcx > > {
230+ ) -> impl Iterator < Item = PlaceElem < ' tcx > > + ' a {
236231 let mut iter = projections
237- . into_iter ( )
232+ . iter ( )
233+ . copied ( )
238234 // Filter out opaque casts, they are unnecessary in the prefix.
239235 . filter ( |elem| !matches ! ( elem, ProjectionElem :: OpaqueCast ( ..) ) ) ;
240236 for projection in prefix_projections {
@@ -258,21 +254,31 @@ fn strip_prefix<'tcx>(
258254}
259255
260256impl < ' 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 ) }
267261 }
268262
269263 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+ }
271278 }
272279
273280 /// 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.
276282 ///
277283 /// Upvars resolve may fail for a `PlaceBuilder` when attempting to
278284 /// resolve a disjoint field whose root variable is not captured
@@ -281,11 +287,14 @@ impl<'tcx> PlaceBuilder<'tcx> {
281287 /// not captured. This can happen because the final mir that will be
282288 /// generated doesn't require a read for this place. Failures will only
283289 /// happen inside closures.
284- pub ( in crate :: build) fn try_upvars_resolved (
285- self ,
290+ pub ( in crate :: build) fn resolve_upvar (
291+ & self ,
286292 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 )
289298 }
290299
291300 pub ( crate ) fn base ( & self ) -> PlaceBase {
0 commit comments