@@ -26,6 +26,7 @@ use crate::ty::util::Discr;
26
26
pub use adt:: * ;
27
27
pub use assoc:: * ;
28
28
pub use generics:: * ;
29
+ use hir:: OpaqueTyOrigin ;
29
30
use rustc_ast as ast;
30
31
use rustc_ast:: node_id:: NodeMap ;
31
32
use rustc_attr as attr;
@@ -1309,6 +1310,7 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
1309
1310
tcx : TyCtxt < ' tcx > ,
1310
1311
// typeck errors have subpar spans for opaque types, so delay error reporting until borrowck.
1311
1312
ignore_errors : bool ,
1313
+ origin : OpaqueTyOrigin ,
1312
1314
) -> Self {
1313
1315
let OpaqueTypeKey { def_id, substs } = opaque_type_key;
1314
1316
@@ -1320,8 +1322,79 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
1320
1322
// shifting.
1321
1323
let id_substs = InternalSubsts :: identity_for_item ( tcx, def_id. to_def_id ( ) ) ;
1322
1324
debug ! ( ?id_substs) ;
1323
- let map: FxHashMap < GenericArg < ' tcx > , GenericArg < ' tcx > > =
1324
- substs. iter ( ) . enumerate ( ) . map ( |( index, subst) | ( subst, id_substs[ index] ) ) . collect ( ) ;
1325
+
1326
+ let map = substs. iter ( ) . zip ( id_substs) ;
1327
+
1328
+ let map: FxHashMap < GenericArg < ' tcx > , GenericArg < ' tcx > > = match origin {
1329
+ // HACK: The HIR lowering for async fn does not generate
1330
+ // any `+ Captures<'x>` bounds for the `impl Future<...>`, so all async fns with lifetimes
1331
+ // would now fail to compile. We should probably just make hir lowering fill this in properly.
1332
+ OpaqueTyOrigin :: AsyncFn ( _) => map. collect ( ) ,
1333
+ OpaqueTyOrigin :: FnReturn ( _) | OpaqueTyOrigin :: TyAlias => {
1334
+ // Opaque types may only use regions that are bound. So for
1335
+ // ```rust
1336
+ // type Foo<'a, 'b, 'c> = impl Trait<'a> + 'b;
1337
+ // ```
1338
+ // we may not use `'c` in the hidden type.
1339
+ struct OpaqueTypeLifetimeCollector < ' tcx > {
1340
+ lifetimes : FxHashSet < ty:: Region < ' tcx > > ,
1341
+ }
1342
+
1343
+ impl < ' tcx > ty:: TypeVisitor < ' tcx > for OpaqueTypeLifetimeCollector < ' tcx > {
1344
+ fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
1345
+ self . lifetimes . insert ( r) ;
1346
+ r. super_visit_with ( self )
1347
+ }
1348
+ }
1349
+
1350
+ let mut collector = OpaqueTypeLifetimeCollector { lifetimes : Default :: default ( ) } ;
1351
+
1352
+ for pred in tcx. bound_explicit_item_bounds ( def_id. to_def_id ( ) ) . transpose_iter ( ) {
1353
+ let pred = pred. map_bound ( |( pred, _) | * pred) . subst ( tcx, id_substs) ;
1354
+
1355
+ trace ! ( pred=?pred. kind( ) ) ;
1356
+
1357
+ // We only ignore opaque type substs if the opaque type is the outermost type.
1358
+ // The opaque type may be nested within itself via recursion in e.g.
1359
+ // type Foo<'a> = impl PartialEq<Foo<'a>>;
1360
+ // which thus mentions `'a` and should thus accept hidden types that borrow 'a
1361
+ // instead of requiring an additional `+ 'a`.
1362
+ match pred. kind ( ) . skip_binder ( ) {
1363
+ ty:: PredicateKind :: Trait ( TraitPredicate {
1364
+ trait_ref : ty:: TraitRef { def_id : _, substs } ,
1365
+ constness : _,
1366
+ polarity : _,
1367
+ } ) => {
1368
+ trace ! ( ?substs) ;
1369
+ for subst in & substs[ 1 ..] {
1370
+ subst. visit_with ( & mut collector) ;
1371
+ }
1372
+ }
1373
+ ty:: PredicateKind :: Projection ( ty:: ProjectionPredicate {
1374
+ projection_ty : ty:: ProjectionTy { substs, item_def_id : _ } ,
1375
+ term,
1376
+ } ) => {
1377
+ for subst in & substs[ 1 ..] {
1378
+ subst. visit_with ( & mut collector) ;
1379
+ }
1380
+ term. visit_with ( & mut collector) ;
1381
+ }
1382
+ _ => {
1383
+ pred. visit_with ( & mut collector) ;
1384
+ }
1385
+ }
1386
+ }
1387
+ let lifetimes = collector. lifetimes ;
1388
+ trace ! ( ?lifetimes) ;
1389
+ map. filter ( |( _, v) | {
1390
+ let ty:: GenericArgKind :: Lifetime ( lt) = v. unpack ( ) else {
1391
+ return true ;
1392
+ } ;
1393
+ lifetimes. contains ( & lt)
1394
+ } )
1395
+ . collect ( )
1396
+ }
1397
+ } ;
1325
1398
debug ! ( "map = {:#?}" , map) ;
1326
1399
1327
1400
// Convert the type from the function into a type valid outside
0 commit comments