@@ -26,6 +26,7 @@ use crate::ty::util::Discr;
2626pub use adt:: * ;
2727pub use assoc:: * ;
2828pub use generics:: * ;
29+ use hir:: OpaqueTyOrigin ;
2930use rustc_ast as ast;
3031use rustc_ast:: node_id:: NodeMap ;
3132use rustc_attr as attr;
@@ -1309,6 +1310,7 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
13091310 tcx : TyCtxt < ' tcx > ,
13101311 // typeck errors have subpar spans for opaque types, so delay error reporting until borrowck.
13111312 ignore_errors : bool ,
1313+ origin : OpaqueTyOrigin ,
13121314 ) -> Self {
13131315 let OpaqueTypeKey { def_id, substs } = opaque_type_key;
13141316
@@ -1320,8 +1322,79 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
13201322 // shifting.
13211323 let id_substs = InternalSubsts :: identity_for_item ( tcx, def_id. to_def_id ( ) ) ;
13221324 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+ } ;
13251398 debug ! ( "map = {:#?}" , map) ;
13261399
13271400 // Convert the type from the function into a type valid outside
0 commit comments