@@ -224,11 +224,30 @@ enum ImplTraitContext<'b, 'a> {
224
224
/// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
225
225
/// equivalent to a new opaque type like `type T = impl Debug; fn foo() -> T`.
226
226
///
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
+ } ,
232
251
/// `impl Trait` is not accepted in this position.
233
252
Disallowed ( ImplTraitPosition ) ,
234
253
}
@@ -253,7 +272,12 @@ impl<'a> ImplTraitContext<'_, 'a> {
253
272
use self :: ImplTraitContext :: * ;
254
273
match self {
255
274
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
+ }
257
281
Disallowed ( pos) => Disallowed ( * pos) ,
258
282
}
259
283
}
@@ -1001,6 +1025,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1001
1025
hir:: TypeBindingKind :: Equality { ty : self . lower_ty ( ty, itctx) }
1002
1026
}
1003
1027
AssocTyConstraintKind :: Bound { ref bounds } => {
1028
+ let mut capturable_lifetimes;
1004
1029
// Piggy-back on the `impl Trait` context to figure out the correct behavior.
1005
1030
let ( desugar_to_impl_trait, itctx) = match itctx {
1006
1031
// We are in the return position:
@@ -1010,7 +1035,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1010
1035
// so desugar to
1011
1036
//
1012
1037
// fn foo() -> impl Iterator<Item = impl Debug>
1013
- ImplTraitContext :: OpaqueTy ( ..) => ( true , itctx) ,
1038
+ ImplTraitContext :: ReturnPositionOpaqueTy { .. }
1039
+ | ImplTraitContext :: OtherOpaqueTy { .. } => ( true , itctx) ,
1014
1040
1015
1041
// We are in the argument position, but within a dyn type:
1016
1042
//
@@ -1028,7 +1054,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1028
1054
//
1029
1055
// FIXME: this is only needed until `impl Trait` is allowed in type aliases.
1030
1056
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
+ )
1032
1065
}
1033
1066
1034
1067
// We are in the parameter position, but not within a dyn type:
@@ -1270,10 +1303,31 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1270
1303
TyKind :: ImplTrait ( def_node_id, ref bounds) => {
1271
1304
let span = t. span ;
1272
1305
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
+ )
1277
1331
}
1278
1332
ImplTraitContext :: Universal ( in_band_ty_params) => {
1279
1333
// Add a definition for the in-band `Param`.
@@ -1351,6 +1405,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1351
1405
fn_def_id : Option < DefId > ,
1352
1406
origin : hir:: OpaqueTyOrigin ,
1353
1407
opaque_ty_node_id : NodeId ,
1408
+ capturable_lifetimes : Option < & FxHashSet < hir:: LifetimeName > > ,
1354
1409
lower_bounds : impl FnOnce ( & mut Self ) -> hir:: GenericBounds < ' hir > ,
1355
1410
) -> hir:: TyKind < ' hir > {
1356
1411
debug ! (
@@ -1371,17 +1426,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1371
1426
1372
1427
let hir_bounds = self . with_hir_id_owner ( opaque_ty_node_id, lower_bounds) ;
1373
1428
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
+ ) ;
1381
1435
1382
- debug ! ( "lower_opaque_impl_trait: lifetimes={:#?}" , lifetimes, ) ;
1436
+ debug ! ( "lower_opaque_impl_trait: lifetimes={:#?}" , lifetimes) ;
1383
1437
1384
- debug ! ( "lower_opaque_impl_trait: lifetime_defs={:#?}" , lifetime_defs, ) ;
1438
+ debug ! ( "lower_opaque_impl_trait: lifetime_defs={:#?}" , lifetime_defs) ;
1385
1439
1386
1440
self . with_hir_id_owner ( opaque_ty_node_id, move |lctx| {
1387
1441
let opaque_ty_item = hir:: OpaqueTy {
@@ -1438,6 +1492,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1438
1492
opaque_ty_id : NodeId ,
1439
1493
parent_def_id : LocalDefId ,
1440
1494
bounds : hir:: GenericBounds < ' hir > ,
1495
+ lifetimes_to_include : Option < & FxHashSet < hir:: LifetimeName > > ,
1441
1496
) -> ( & ' hir [ hir:: GenericArg < ' hir > ] , & ' hir [ hir:: GenericParam < ' hir > ] ) {
1442
1497
debug ! (
1443
1498
"lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \
@@ -1458,6 +1513,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1458
1513
already_defined_lifetimes : FxHashSet < hir:: LifetimeName > ,
1459
1514
output_lifetimes : Vec < hir:: GenericArg < ' hir > > ,
1460
1515
output_lifetime_params : Vec < hir:: GenericParam < ' hir > > ,
1516
+ lifetimes_to_include : Option < & ' r FxHashSet < hir:: LifetimeName > > ,
1461
1517
}
1462
1518
1463
1519
impl < ' r , ' a , ' v , ' hir > intravisit:: Visitor < ' v > for ImplTraitLifetimeCollector < ' r , ' a , ' hir > {
@@ -1543,6 +1599,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1543
1599
1544
1600
if !self . currently_bound_lifetimes . contains ( & name)
1545
1601
&& !self . already_defined_lifetimes . contains ( & name)
1602
+ && self . lifetimes_to_include . map_or ( true , |lifetimes| lifetimes. contains ( & name) )
1546
1603
{
1547
1604
self . already_defined_lifetimes . insert ( name) ;
1548
1605
@@ -1596,6 +1653,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1596
1653
already_defined_lifetimes : FxHashSet :: default ( ) ,
1597
1654
output_lifetimes : Vec :: new ( ) ,
1598
1655
output_lifetime_params : Vec :: new ( ) ,
1656
+ lifetimes_to_include,
1599
1657
} ;
1600
1658
1601
1659
for bound in bounds {
@@ -1620,10 +1678,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1620
1678
}
1621
1679
}
1622
1680
let ty = l. ty . as_ref ( ) . map ( |t| {
1681
+ let mut capturable_lifetimes;
1623
1682
self . lower_ty (
1624
1683
t,
1625
1684
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
+ }
1627
1690
} else {
1628
1691
ImplTraitContext :: Disallowed ( ImplTraitPosition :: Binding )
1629
1692
} ,
@@ -1726,7 +1789,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1726
1789
FnRetTy :: Ty ( ref ty) => {
1727
1790
let context = match in_band_ty_params {
1728
1791
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
+ }
1730
1796
}
1731
1797
_ => ImplTraitContext :: disallowed ( ) ,
1732
1798
} ;
@@ -1945,7 +2011,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1945
2011
// Foo = impl Trait` is, internally, created as a child of the
1946
2012
// async fn, so the *type parameters* are inherited. It's
1947
2013
// 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) ;
1949
2015
let opaque_ty = self . ty ( opaque_ty_span, opaque_ty_ref) ;
1950
2016
hir:: FnRetTy :: Return ( self . arena . alloc ( opaque_ty) )
1951
2017
}
@@ -1963,8 +2029,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1963
2029
// Not `OpaqueTyOrigin::AsyncFn`: that's only used for the
1964
2030
// `impl Future` opaque type that `async fn` implicitly
1965
2031
// 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
+ } ;
1968
2036
self . lower_ty ( ty, context)
1969
2037
}
1970
2038
FnRetTy :: Default ( ret_ty_span) => self . arena . alloc ( self . ty_tup ( * ret_ty_span, & [ ] ) ) ,
@@ -2114,7 +2182,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
2114
2182
default : default. as_ref ( ) . map ( |x| {
2115
2183
self . lower_ty (
2116
2184
x,
2117
- ImplTraitContext :: OpaqueTy ( None , hir:: OpaqueTyOrigin :: Misc ) ,
2185
+ ImplTraitContext :: OtherOpaqueTy {
2186
+ capturable_lifetimes : & mut FxHashSet :: default ( ) ,
2187
+ origin : hir:: OpaqueTyOrigin :: Misc ,
2188
+ } ,
2118
2189
)
2119
2190
} ) ,
2120
2191
synthetic : param
@@ -2170,8 +2241,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
2170
2241
& NodeMap :: default ( ) ,
2171
2242
itctx. reborrow ( ) ,
2172
2243
) ;
2244
+
2173
2245
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
2175
2266
} ) ;
2176
2267
2177
2268
hir:: PolyTraitRef { bound_generic_params, trait_ref, span : p. span }
0 commit comments