@@ -224,11 +224,30 @@ enum ImplTraitContext<'b, 'a> {
224224 /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
225225 /// equivalent to a new opaque type like `type T = impl Debug; fn foo() -> T`.
226226 ///
227- /// We optionally store a `DefId` for the parent item here so we can look up necessary
228- /// information later. It is `None` when no information about the context should be stored
229- /// (e.g., for consts and statics).
230- OpaqueTy ( Option < DefId > /* fn def-ID */ , hir:: OpaqueTyOrigin ) ,
231-
227+ ReturnPositionOpaqueTy {
228+ /// `DefId` for the parent function, used to look up necessary
229+ /// information later.
230+ fn_def_id : DefId ,
231+ /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn,
232+ origin : hir:: OpaqueTyOrigin ,
233+ } ,
234+ /// Impl trait in type aliases, consts and statics.
235+ OtherOpaqueTy {
236+ /// Set of lifetimes that this opaque type can capture, if it uses
237+ /// them. This includes lifetimes bound since we entered this context.
238+ /// For example, in
239+ ///
240+ /// type A<'b> = impl for<'a> Trait<'a, Out = impl Sized + 'a>;
241+ ///
242+ /// the inner opaque type captures `'a` because it uses it. It doesn't
243+ /// need to capture `'b` because it already inherits the lifetime
244+ /// parameter from `A`.
245+ // FIXME(impl_trait): but `required_region_bounds` will ICE later
246+ // anyway.
247+ capturable_lifetimes : & ' b mut FxHashSet < hir:: LifetimeName > ,
248+ /// Origin: Either OpaqueTyOrigin::Misc or OpaqueTyOrigin::Binding,
249+ origin : hir:: OpaqueTyOrigin ,
250+ } ,
232251 /// `impl Trait` is not accepted in this position.
233252 Disallowed ( ImplTraitPosition ) ,
234253}
@@ -253,7 +272,12 @@ impl<'a> ImplTraitContext<'_, 'a> {
253272 use self :: ImplTraitContext :: * ;
254273 match self {
255274 Universal ( params) => Universal ( params) ,
256- OpaqueTy ( fn_def_id, origin) => OpaqueTy ( * fn_def_id, * origin) ,
275+ ReturnPositionOpaqueTy { fn_def_id, origin } => {
276+ ReturnPositionOpaqueTy { fn_def_id : * fn_def_id, origin : * origin }
277+ }
278+ OtherOpaqueTy { capturable_lifetimes, origin } => {
279+ OtherOpaqueTy { capturable_lifetimes, origin : * origin }
280+ }
257281 Disallowed ( pos) => Disallowed ( * pos) ,
258282 }
259283 }
@@ -1001,6 +1025,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
10011025 hir:: TypeBindingKind :: Equality { ty : self . lower_ty ( ty, itctx) }
10021026 }
10031027 AssocTyConstraintKind :: Bound { ref bounds } => {
1028+ let mut capturable_lifetimes;
10041029 // Piggy-back on the `impl Trait` context to figure out the correct behavior.
10051030 let ( desugar_to_impl_trait, itctx) = match itctx {
10061031 // We are in the return position:
@@ -1010,7 +1035,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
10101035 // so desugar to
10111036 //
10121037 // fn foo() -> impl Iterator<Item = impl Debug>
1013- ImplTraitContext :: OpaqueTy ( ..) => ( true , itctx) ,
1038+ ImplTraitContext :: ReturnPositionOpaqueTy { .. }
1039+ | ImplTraitContext :: OtherOpaqueTy { .. } => ( true , itctx) ,
10141040
10151041 // We are in the argument position, but within a dyn type:
10161042 //
@@ -1028,7 +1054,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
10281054 //
10291055 // FIXME: this is only needed until `impl Trait` is allowed in type aliases.
10301056 ImplTraitContext :: Disallowed ( _) if self . is_in_dyn_type => {
1031- ( true , ImplTraitContext :: OpaqueTy ( None , hir:: OpaqueTyOrigin :: Misc ) )
1057+ capturable_lifetimes = FxHashSet :: default ( ) ;
1058+ (
1059+ true ,
1060+ ImplTraitContext :: OtherOpaqueTy {
1061+ capturable_lifetimes : & mut capturable_lifetimes,
1062+ origin : hir:: OpaqueTyOrigin :: Misc ,
1063+ } ,
1064+ )
10321065 }
10331066
10341067 // We are in the parameter position, but not within a dyn type:
@@ -1270,10 +1303,31 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12701303 TyKind :: ImplTrait ( def_node_id, ref bounds) => {
12711304 let span = t. span ;
12721305 match itctx {
1273- ImplTraitContext :: OpaqueTy ( fn_def_id, origin) => {
1274- self . lower_opaque_impl_trait ( span, fn_def_id, origin, def_node_id, |this| {
1275- this. lower_param_bounds ( bounds, itctx)
1276- } )
1306+ ImplTraitContext :: ReturnPositionOpaqueTy { fn_def_id, origin } => self
1307+ . lower_opaque_impl_trait (
1308+ span,
1309+ Some ( fn_def_id) ,
1310+ origin,
1311+ def_node_id,
1312+ None ,
1313+ |this| this. lower_param_bounds ( bounds, itctx) ,
1314+ ) ,
1315+ ImplTraitContext :: OtherOpaqueTy { ref capturable_lifetimes, origin } => {
1316+ // Reset capturable lifetimes, any nested impl trait
1317+ // types will inherit lifetimes from this opaque type,
1318+ // so don't need to capture them again.
1319+ let nested_itctx = ImplTraitContext :: OtherOpaqueTy {
1320+ capturable_lifetimes : & mut FxHashSet :: default ( ) ,
1321+ origin,
1322+ } ;
1323+ self . lower_opaque_impl_trait (
1324+ span,
1325+ None ,
1326+ origin,
1327+ def_node_id,
1328+ Some ( capturable_lifetimes) ,
1329+ |this| this. lower_param_bounds ( bounds, nested_itctx) ,
1330+ )
12771331 }
12781332 ImplTraitContext :: Universal ( in_band_ty_params) => {
12791333 // Add a definition for the in-band `Param`.
@@ -1351,6 +1405,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
13511405 fn_def_id : Option < DefId > ,
13521406 origin : hir:: OpaqueTyOrigin ,
13531407 opaque_ty_node_id : NodeId ,
1408+ capturable_lifetimes : Option < & FxHashSet < hir:: LifetimeName > > ,
13541409 lower_bounds : impl FnOnce ( & mut Self ) -> hir:: GenericBounds < ' hir > ,
13551410 ) -> hir:: TyKind < ' hir > {
13561411 debug ! (
@@ -1371,17 +1426,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
13711426
13721427 let hir_bounds = self . with_hir_id_owner ( opaque_ty_node_id, lower_bounds) ;
13731428
1374- let ( lifetimes, lifetime_defs) : ( & [ _ ] , & [ _ ] ) = if fn_def_id. is_some ( ) {
1375- self . lifetimes_from_impl_trait_bounds ( opaque_ty_node_id, opaque_ty_def_id, & hir_bounds)
1376- } else {
1377- // Non return-position impl trait captures all of the lifetimes of
1378- // the parent item.
1379- ( & [ ] , & [ ] )
1380- } ;
1429+ let ( lifetimes, lifetime_defs) = self . lifetimes_from_impl_trait_bounds (
1430+ opaque_ty_node_id,
1431+ opaque_ty_def_id,
1432+ & hir_bounds,
1433+ capturable_lifetimes,
1434+ ) ;
13811435
1382- debug ! ( "lower_opaque_impl_trait: lifetimes={:#?}" , lifetimes, ) ;
1436+ debug ! ( "lower_opaque_impl_trait: lifetimes={:#?}" , lifetimes) ;
13831437
1384- debug ! ( "lower_opaque_impl_trait: lifetime_defs={:#?}" , lifetime_defs, ) ;
1438+ debug ! ( "lower_opaque_impl_trait: lifetime_defs={:#?}" , lifetime_defs) ;
13851439
13861440 self . with_hir_id_owner ( opaque_ty_node_id, move |lctx| {
13871441 let opaque_ty_item = hir:: OpaqueTy {
@@ -1438,6 +1492,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
14381492 opaque_ty_id : NodeId ,
14391493 parent_def_id : LocalDefId ,
14401494 bounds : hir:: GenericBounds < ' hir > ,
1495+ lifetimes_to_include : Option < & FxHashSet < hir:: LifetimeName > > ,
14411496 ) -> ( & ' hir [ hir:: GenericArg < ' hir > ] , & ' hir [ hir:: GenericParam < ' hir > ] ) {
14421497 debug ! (
14431498 "lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \
@@ -1458,6 +1513,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
14581513 already_defined_lifetimes : FxHashSet < hir:: LifetimeName > ,
14591514 output_lifetimes : Vec < hir:: GenericArg < ' hir > > ,
14601515 output_lifetime_params : Vec < hir:: GenericParam < ' hir > > ,
1516+ lifetimes_to_include : Option < & ' r FxHashSet < hir:: LifetimeName > > ,
14611517 }
14621518
14631519 impl < ' r , ' a , ' v , ' hir > intravisit:: Visitor < ' v > for ImplTraitLifetimeCollector < ' r , ' a , ' hir > {
@@ -1543,6 +1599,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15431599
15441600 if !self . currently_bound_lifetimes . contains ( & name)
15451601 && !self . already_defined_lifetimes . contains ( & name)
1602+ && self . lifetimes_to_include . map_or ( true , |lifetimes| lifetimes. contains ( & name) )
15461603 {
15471604 self . already_defined_lifetimes . insert ( name) ;
15481605
@@ -1596,6 +1653,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15961653 already_defined_lifetimes : FxHashSet :: default ( ) ,
15971654 output_lifetimes : Vec :: new ( ) ,
15981655 output_lifetime_params : Vec :: new ( ) ,
1656+ lifetimes_to_include,
15991657 } ;
16001658
16011659 for bound in bounds {
@@ -1620,10 +1678,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
16201678 }
16211679 }
16221680 let ty = l. ty . as_ref ( ) . map ( |t| {
1681+ let mut capturable_lifetimes;
16231682 self . lower_ty (
16241683 t,
16251684 if self . sess . features_untracked ( ) . impl_trait_in_bindings {
1626- ImplTraitContext :: OpaqueTy ( None , hir:: OpaqueTyOrigin :: Binding )
1685+ capturable_lifetimes = FxHashSet :: default ( ) ;
1686+ ImplTraitContext :: OtherOpaqueTy {
1687+ capturable_lifetimes : & mut capturable_lifetimes,
1688+ origin : hir:: OpaqueTyOrigin :: Binding ,
1689+ }
16271690 } else {
16281691 ImplTraitContext :: Disallowed ( ImplTraitPosition :: Binding )
16291692 } ,
@@ -1726,7 +1789,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17261789 FnRetTy :: Ty ( ref ty) => {
17271790 let context = match in_band_ty_params {
17281791 Some ( ( def_id, _) ) if impl_trait_return_allow => {
1729- ImplTraitContext :: OpaqueTy ( Some ( def_id) , hir:: OpaqueTyOrigin :: FnReturn )
1792+ ImplTraitContext :: ReturnPositionOpaqueTy {
1793+ fn_def_id : def_id,
1794+ origin : hir:: OpaqueTyOrigin :: FnReturn ,
1795+ }
17301796 }
17311797 _ => ImplTraitContext :: disallowed ( ) ,
17321798 } ;
@@ -1945,7 +2011,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19452011 // Foo = impl Trait` is, internally, created as a child of the
19462012 // async fn, so the *type parameters* are inherited. It's
19472013 // only the lifetime parameters that we must supply.
1948- let opaque_ty_ref = hir:: TyKind :: Def ( hir:: ItemId { id : opaque_ty_id } , generic_args) ;
2014+ let opaque_ty_ref = hir:: TyKind :: OpaqueDef ( hir:: ItemId { id : opaque_ty_id } , generic_args) ;
19492015 let opaque_ty = self . ty ( opaque_ty_span, opaque_ty_ref) ;
19502016 hir:: FnRetTy :: Return ( self . arena . alloc ( opaque_ty) )
19512017 }
@@ -1963,8 +2029,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19632029 // Not `OpaqueTyOrigin::AsyncFn`: that's only used for the
19642030 // `impl Future` opaque type that `async fn` implicitly
19652031 // generates.
1966- let context =
1967- ImplTraitContext :: OpaqueTy ( Some ( fn_def_id) , hir:: OpaqueTyOrigin :: FnReturn ) ;
2032+ let context = ImplTraitContext :: ReturnPositionOpaqueTy {
2033+ fn_def_id,
2034+ origin : hir:: OpaqueTyOrigin :: FnReturn ,
2035+ } ;
19682036 self . lower_ty ( ty, context)
19692037 }
19702038 FnRetTy :: Default ( ret_ty_span) => self . arena . alloc ( self . ty_tup ( * ret_ty_span, & [ ] ) ) ,
@@ -2114,7 +2182,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
21142182 default : default. as_ref ( ) . map ( |x| {
21152183 self . lower_ty (
21162184 x,
2117- ImplTraitContext :: OpaqueTy ( None , hir:: OpaqueTyOrigin :: Misc ) ,
2185+ ImplTraitContext :: OtherOpaqueTy {
2186+ capturable_lifetimes : & mut FxHashSet :: default ( ) ,
2187+ origin : hir:: OpaqueTyOrigin :: Misc ,
2188+ } ,
21182189 )
21192190 } ) ,
21202191 synthetic : param
@@ -2170,8 +2241,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
21702241 & NodeMap :: default ( ) ,
21712242 itctx. reborrow ( ) ,
21722243 ) ;
2244+
21732245 let trait_ref = self . with_in_scope_lifetime_defs ( & p. bound_generic_params , |this| {
2174- this. lower_trait_ref ( & p. trait_ref , itctx)
2246+ // Any impl Trait types defined within this scope can capture
2247+ // lifetimes bound on this predicate.
2248+ let lt_def_names = p. bound_generic_params . iter ( ) . filter_map ( |param| match param. kind {
2249+ GenericParamKind :: Lifetime { .. } => Some ( hir:: LifetimeName :: Param (
2250+ ParamName :: Plain ( param. ident . normalize_to_macros_2_0 ( ) ) ,
2251+ ) ) ,
2252+ _ => None ,
2253+ } ) ;
2254+ if let ImplTraitContext :: OtherOpaqueTy { ref mut capturable_lifetimes, .. } = itctx {
2255+ capturable_lifetimes. extend ( lt_def_names. clone ( ) ) ;
2256+ }
2257+
2258+ let res = this. lower_trait_ref ( & p. trait_ref , itctx. reborrow ( ) ) ;
2259+
2260+ if let ImplTraitContext :: OtherOpaqueTy { ref mut capturable_lifetimes, .. } = itctx {
2261+ for param in lt_def_names {
2262+ capturable_lifetimes. remove ( & param) ;
2263+ }
2264+ }
2265+ res
21752266 } ) ;
21762267
21772268 hir:: PolyTraitRef { bound_generic_params, trait_ref, span : p. span }
0 commit comments