@@ -7,6 +7,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
7
7
use rustc_middle:: hir:: place:: Projection as HirProjection ;
8
8
use rustc_middle:: hir:: place:: ProjectionKind as HirProjectionKind ;
9
9
use rustc_middle:: middle:: region;
10
+ use rustc_middle:: mir:: tcx:: PlaceTy ;
10
11
use rustc_middle:: mir:: AssertKind :: BoundsCheck ;
11
12
use rustc_middle:: mir:: * ;
12
13
use rustc_middle:: thir:: * ;
@@ -104,8 +105,9 @@ fn convert_to_hir_projections_and_truncate_for_capture<'tcx>(
104
105
variant = Some ( * idx) ;
105
106
continue ;
106
107
}
108
+ // These do not affect anything, they just make sure we know the right type.
109
+ ProjectionElem :: OpaqueCast ( _) => continue ,
107
110
ProjectionElem :: Index ( ..)
108
- | ProjectionElem :: OpaqueCast ( _)
109
111
| ProjectionElem :: ConstantIndex { .. }
110
112
| ProjectionElem :: Subslice { .. } => {
111
113
// We don't capture array-access projections.
@@ -297,16 +299,21 @@ fn strip_prefix<'tcx>(
297
299
prefix_projections : & [ HirProjection < ' tcx > ] ,
298
300
) -> impl Iterator < Item = PlaceElem < ' tcx > > {
299
301
let mut iter = projections. into_iter ( ) ;
302
+ let mut next = || match iter. next ( ) ? {
303
+ // Filter out opaque casts, they are unnecessary in the prefix.
304
+ ProjectionElem :: OpaqueCast ( ..) => iter. next ( ) ,
305
+ other => Some ( other) ,
306
+ } ;
300
307
for projection in prefix_projections {
301
308
match projection. kind {
302
309
HirProjectionKind :: Deref => {
303
- assert ! ( matches!( iter . next( ) , Some ( ProjectionElem :: Deref ) ) ) ;
310
+ assert ! ( matches!( next( ) , Some ( ProjectionElem :: Deref ) ) ) ;
304
311
}
305
312
HirProjectionKind :: Field ( ..) => {
306
313
if base_ty. is_enum ( ) {
307
- assert ! ( matches!( iter . next( ) , Some ( ProjectionElem :: Downcast ( ..) ) ) ) ;
314
+ assert ! ( matches!( next( ) , Some ( ProjectionElem :: Downcast ( ..) ) ) ) ;
308
315
}
309
- assert ! ( matches!( iter . next( ) , Some ( ProjectionElem :: Field ( ..) ) ) ) ;
316
+ assert ! ( matches!( next( ) , Some ( ProjectionElem :: Field ( ..) ) ) ) ;
310
317
}
311
318
HirProjectionKind :: Index | HirProjectionKind :: Subslice => {
312
319
bug ! ( "unexpected projection kind: {:?}" , projection) ;
@@ -320,7 +327,23 @@ fn strip_prefix<'tcx>(
320
327
impl < ' tcx > PlaceBuilder < ' tcx > {
321
328
pub ( crate ) fn into_place ( self , cx : & Builder < ' _ , ' tcx > ) -> Place < ' tcx > {
322
329
if let PlaceBase :: Local ( local) = self . base {
323
- Place { local, projection : cx. tcx . intern_place_elems ( & self . projection ) }
330
+ let mut projections = vec ! [ ] ;
331
+ let mut ty = PlaceTy :: from_ty ( cx. local_decls [ local] . ty ) ;
332
+ for projection in self . projection {
333
+ // Only preserve those opaque casts that actually go from an opaque type
334
+ // to another type.
335
+ if let ProjectionElem :: OpaqueCast ( t) = projection {
336
+ if let ty:: Opaque ( ..) = ty. ty . kind ( ) {
337
+ if t != ty. ty {
338
+ projections. push ( ProjectionElem :: OpaqueCast ( t) ) ;
339
+ }
340
+ }
341
+ } else {
342
+ projections. push ( projection) ;
343
+ }
344
+ ty = ty. projection_ty ( cx. tcx , projection) ;
345
+ }
346
+ Place { local, projection : cx. tcx . intern_place_elems ( & projections) }
324
347
} else {
325
348
self . expect_upvars_resolved ( cx) . into_place ( cx)
326
349
}
0 commit comments