32
32
33
33
#![ feature( crate_visibility_modifier) ]
34
34
#![ feature( box_patterns) ]
35
+ #![ feature( let_chains) ]
35
36
#![ feature( let_else) ]
36
37
#![ feature( never_type) ]
37
38
#![ recursion_limit = "256" ]
@@ -135,24 +136,8 @@ struct LoweringContext<'a, 'hir: 'a> {
135
136
/// Currently in-scope lifetimes defined in impl headers, fn headers, or HRTB.
136
137
in_scope_lifetimes : Vec < ( ParamName , LocalDefId ) > ,
137
138
138
- /// Used to handle lifetimes appearing in impl-traits. When we lower a lifetime,
139
- /// it is inserted in the `FxHashMap`, and the resolution is modified so to point
140
- /// to the lifetime parameter impl-trait will generate.
141
- /// When traversing `for<...>` binders, they are inserted in the `FxHashSet` so
142
- /// we know *not* to rebind the introduced lifetimes.
143
- captured_lifetimes : Option < (
144
- LocalDefId , // parent def_id for new definitions
145
- FxHashMap <
146
- LocalDefId , // original parameter id
147
- (
148
- Span , // Span
149
- NodeId , // synthetized parameter id
150
- ParamName , // parameter name
151
- LifetimeRes , // original resolution
152
- ) ,
153
- > ,
154
- FxHashSet < NodeId > , // traversed binders, to ignore
155
- ) > ,
139
+ /// Used to handle lifetimes appearing in impl-traits.
140
+ captured_lifetimes : Option < LifetimeCaptureContext > ,
156
141
157
142
current_hir_id_owner : LocalDefId ,
158
143
item_local_id_counter : hir:: ItemLocalId ,
@@ -179,6 +164,9 @@ pub enum LifetimeRes {
179
164
/// - a TraitRef's ref_id, identifying the `for<...>` binder;
180
165
/// - a BareFn type's id;
181
166
/// - a Path's id when this path has parenthesized generic args.
167
+ ///
168
+ /// This information is used for impl-trait lifetime captures, to know when to or not to
169
+ /// capture any given lifetime.
182
170
binder : NodeId ,
183
171
} ,
184
172
/// Created a generic parameter for an anonymous lifetime.
@@ -206,6 +194,28 @@ pub enum LifetimeRes {
206
194
ElidedAnchor { start : NodeId , end : NodeId } ,
207
195
}
208
196
197
+ /// When we lower a lifetime, it is inserted in `captures`, and the resolution is modified so
198
+ /// to point to the lifetime parameter impl-trait will generate.
199
+ /// When traversing `for<...>` binders, they are inserted in `binders_to_ignore` so we know *not*
200
+ /// to rebind the introduced lifetimes.
201
+ #[ derive( Debug ) ]
202
+ struct LifetimeCaptureContext {
203
+ /// parent def_id for new definitions
204
+ parent_def_id : LocalDefId ,
205
+ /// Set of lifetimes to rebind.
206
+ captures : FxHashMap <
207
+ LocalDefId , // original parameter id
208
+ (
209
+ Span , // Span
210
+ NodeId , // synthetized parameter id
211
+ ParamName , // parameter name
212
+ LifetimeRes , // original resolution
213
+ ) ,
214
+ > ,
215
+ /// Traversed binders. The ids in this set should *not* be rebound.
216
+ binders_to_ignore : FxHashSet < NodeId > ,
217
+ }
218
+
209
219
pub trait ResolverAstLowering {
210
220
fn def_key ( & self , id : DefId ) -> DefKey ;
211
221
@@ -790,6 +800,45 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
790
800
( lowered_generics, res)
791
801
}
792
802
803
+ /// Setup lifetime capture for and impl-trait.
804
+ /// The captures will be added to `captures`.
805
+ fn while_capturing_lifetimes < T > (
806
+ & mut self ,
807
+ parent_def_id : LocalDefId ,
808
+ captures : & mut FxHashMap < LocalDefId , ( Span , NodeId , ParamName , LifetimeRes ) > ,
809
+ f : impl FnOnce ( & mut Self ) -> T ,
810
+ ) -> T {
811
+ let lifetime_stash = std:: mem:: replace (
812
+ & mut self . captured_lifetimes ,
813
+ Some ( LifetimeCaptureContext {
814
+ parent_def_id,
815
+ captures : std:: mem:: take ( captures) ,
816
+ binders_to_ignore : Default :: default ( ) ,
817
+ } ) ,
818
+ ) ;
819
+
820
+ let ret = f ( self ) ;
821
+
822
+ let ctxt = std:: mem:: replace ( & mut self . captured_lifetimes , lifetime_stash) . unwrap ( ) ;
823
+ * captures = ctxt. captures ;
824
+
825
+ ret
826
+ }
827
+
828
+ /// Register a binder to be ignored for lifetime capture.
829
+ #[ tracing:: instrument( level = "debug" , skip( self , f) ) ]
830
+ #[ inline]
831
+ fn with_lifetime_binder < T > ( & mut self , binder : NodeId , f : impl FnOnce ( & mut Self ) -> T ) -> T {
832
+ if let Some ( ctxt) = & mut self . captured_lifetimes {
833
+ ctxt. binders_to_ignore . insert ( binder) ;
834
+ }
835
+ let ret = f ( self ) ;
836
+ if let Some ( ctxt) = & mut self . captured_lifetimes {
837
+ ctxt. binders_to_ignore . remove ( & binder) ;
838
+ }
839
+ ret
840
+ }
841
+
793
842
fn with_dyn_type_scope < T > ( & mut self , in_scope : bool , f : impl FnOnce ( & mut Self ) -> T ) -> T {
794
843
let was_in_dyn_type = self . is_in_dyn_type ;
795
844
self . is_in_dyn_type = in_scope;
@@ -1197,25 +1246,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1197
1246
hir:: TyKind :: Rptr ( lifetime, self . lower_mt ( mt, itctx) )
1198
1247
}
1199
1248
TyKind :: BareFn ( ref f) => self . with_in_scope_lifetime_defs ( & f. generic_params , |this| {
1200
- if let Some ( ( _, _, binders) ) = & mut this. captured_lifetimes {
1201
- binders. insert ( t. id ) ;
1202
- }
1203
-
1204
- let ret = hir:: TyKind :: BareFn ( this. arena . alloc ( hir:: BareFnTy {
1205
- generic_params : this. lower_generic_params (
1206
- & f. generic_params ,
1207
- ImplTraitContext :: Disallowed ( ImplTraitPosition :: Generic ) ,
1208
- ) ,
1209
- unsafety : this. lower_unsafety ( f. unsafety ) ,
1210
- abi : this. lower_extern ( f. ext ) ,
1211
- decl : this. lower_fn_decl ( & f. decl , None , FnDeclKind :: Pointer , None ) ,
1212
- param_names : this. lower_fn_params_to_names ( & f. decl ) ,
1213
- } ) ) ;
1214
-
1215
- if let Some ( ( _, _, binders) ) = & mut this. captured_lifetimes {
1216
- binders. remove ( & t. id ) ;
1217
- }
1218
- ret
1249
+ this. with_lifetime_binder ( t. id , |this| {
1250
+ hir:: TyKind :: BareFn ( this. arena . alloc ( hir:: BareFnTy {
1251
+ generic_params : this. lower_generic_params (
1252
+ & f. generic_params ,
1253
+ ImplTraitContext :: Disallowed ( ImplTraitPosition :: Generic ) ,
1254
+ ) ,
1255
+ unsafety : this. lower_unsafety ( f. unsafety ) ,
1256
+ abi : this. lower_extern ( f. ext ) ,
1257
+ decl : this. lower_fn_decl ( & f. decl , None , FnDeclKind :: Pointer , None ) ,
1258
+ param_names : this. lower_fn_params_to_names ( & f. decl ) ,
1259
+ } ) )
1260
+ } )
1219
1261
} ) ,
1220
1262
TyKind :: Never => hir:: TyKind :: Never ,
1221
1263
TyKind :: Tup ( ref tys) => {
@@ -1366,15 +1408,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1366
1408
1367
1409
let mut collected_lifetimes = FxHashMap :: default ( ) ;
1368
1410
self . with_hir_id_owner ( opaque_ty_node_id, |lctx| {
1369
- let capture_framework = if origin == hir:: OpaqueTyOrigin :: TyAlias {
1370
- None
1411
+ let hir_bounds = if origin == hir:: OpaqueTyOrigin :: TyAlias {
1412
+ lower_bounds ( lctx )
1371
1413
} else {
1372
- Some ( ( opaque_ty_def_id, FxHashMap :: default ( ) , FxHashSet :: default ( ) ) )
1414
+ lctx. while_capturing_lifetimes (
1415
+ opaque_ty_def_id,
1416
+ & mut collected_lifetimes,
1417
+ lower_bounds,
1418
+ )
1373
1419
} ;
1374
- let lifetime_stash = std:: mem:: replace ( & mut lctx. captured_lifetimes , capture_framework) ;
1375
- let hir_bounds = lower_bounds ( lctx) ;
1376
- collected_lifetimes = std:: mem:: replace ( & mut lctx. captured_lifetimes , lifetime_stash)
1377
- . map_or_else ( FxHashMap :: default, |c| c. 1 ) ;
1378
1420
debug ! ( ?collected_lifetimes) ;
1379
1421
1380
1422
let lifetime_defs = lctx. arena . alloc_from_iter ( collected_lifetimes. iter ( ) . map (
@@ -1716,24 +1758,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1716
1758
debug ! ( ?captures) ;
1717
1759
1718
1760
self . with_hir_id_owner ( opaque_ty_node_id, |this| {
1719
- let lifetime_stash = std:: mem:: replace (
1720
- & mut this. captured_lifetimes ,
1721
- Some ( ( opaque_ty_def_id, std:: mem:: take ( & mut captures) , FxHashSet :: default ( ) ) ) ,
1722
- ) ;
1723
1761
debug ! ( "lower_async_fn_ret_ty: lifetimes_to_define={:#?}" , this. lifetimes_to_define) ;
1724
-
1725
- // We have to be careful to get elision right here. The
1726
- // idea is that we create a lifetime parameter for each
1727
- // lifetime in the return type. So, given a return type
1728
- // like `async fn foo(..) -> &[&u32]`, we lower to `impl
1729
- // Future<Output = &'1 [ &'2 u32 ]>`.
1730
- //
1731
- // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and
1732
- // hence the elision takes place at the fn site.
1733
1762
let future_bound =
1734
- this. lower_async_fn_output_type_to_future_bound ( output, fn_def_id, span) ;
1763
+ this. while_capturing_lifetimes ( opaque_ty_def_id, & mut captures, |this| {
1764
+ // We have to be careful to get elision right here. The
1765
+ // idea is that we create a lifetime parameter for each
1766
+ // lifetime in the return type. So, given a return type
1767
+ // like `async fn foo(..) -> &[&u32]`, we lower to `impl
1768
+ // Future<Output = &'1 [ &'2 u32 ]>`.
1769
+ //
1770
+ // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and
1771
+ // hence the elision takes place at the fn site.
1772
+ this. lower_async_fn_output_type_to_future_bound ( output, fn_def_id, span)
1773
+ } ) ;
1735
1774
debug ! ( "lower_async_fn_ret_ty: future_bound={:#?}" , future_bound) ;
1736
- captures = std:: mem:: replace ( & mut this. captured_lifetimes , lifetime_stash) . unwrap ( ) . 1 ;
1737
1775
debug ! ( "lower_async_fn_ret_ty: captures={:#?}" , captures) ;
1738
1776
1739
1777
let generic_params =
@@ -1882,22 +1920,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1882
1920
LifetimeRes :: Param { param, binder } => {
1883
1921
debug_assert_ne ! ( ident. name, kw:: UnderscoreLifetime ) ;
1884
1922
let p_name = ParamName :: Plain ( ident) ;
1885
- if let Some ( ( parent_def_id, captures, binders) ) = & mut self . captured_lifetimes {
1923
+ if let Some ( LifetimeCaptureContext { parent_def_id, captures, binders_to_ignore } ) =
1924
+ & mut self . captured_lifetimes
1925
+ && !binders_to_ignore. contains ( & binder)
1926
+ {
1886
1927
match captures. entry ( param) {
1887
1928
Entry :: Occupied ( _) => { }
1888
1929
Entry :: Vacant ( v) => {
1889
- if !binders. contains ( & binder) {
1890
- let p_id = self . resolver . next_node_id ( ) ;
1891
- self . resolver . create_def (
1892
- * parent_def_id,
1893
- p_id,
1894
- DefPathData :: LifetimeNs ( p_name. ident ( ) . name ) ,
1895
- ExpnId :: root ( ) ,
1896
- span. with_parent ( None ) ,
1897
- ) ;
1898
-
1899
- v. insert ( ( span, p_id, p_name, res) ) ;
1900
- }
1930
+ let p_id = self . resolver . next_node_id ( ) ;
1931
+ self . resolver . create_def (
1932
+ * parent_def_id,
1933
+ p_id,
1934
+ DefPathData :: LifetimeNs ( p_name. ident ( ) . name ) ,
1935
+ ExpnId :: root ( ) ,
1936
+ span. with_parent ( None ) ,
1937
+ ) ;
1938
+
1939
+ v. insert ( ( span, p_id, p_name, res) ) ;
1901
1940
}
1902
1941
}
1903
1942
}
@@ -1908,24 +1947,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1908
1947
// Only items are allowed to introduce fresh lifetimes,
1909
1948
// so we know `binder` has a `LocalDefId`.
1910
1949
let binder_def_id = self . resolver . local_def_id ( binder) ;
1911
- if let Some ( ( parent_def_id, captures, binders) ) = & mut self . captured_lifetimes {
1950
+ if let Some ( LifetimeCaptureContext { parent_def_id, captures, binders_to_ignore } ) =
1951
+ & mut self . captured_lifetimes
1952
+ && !binders_to_ignore. contains ( & binder)
1953
+ {
1912
1954
match captures. entry ( param) {
1913
1955
Entry :: Occupied ( o) => param = self . resolver . local_def_id ( o. get ( ) . 1 ) ,
1914
1956
Entry :: Vacant ( v) => {
1915
- if !binders. contains ( & binder) {
1916
- let p_id = self . resolver . next_node_id ( ) ;
1917
- let p_def_id = self . resolver . create_def (
1918
- * parent_def_id,
1919
- p_id,
1920
- DefPathData :: LifetimeNs ( kw:: UnderscoreLifetime ) ,
1921
- ExpnId :: root ( ) ,
1922
- span. with_parent ( None ) ,
1923
- ) ;
1924
-
1925
- let p_name = ParamName :: Fresh ( param) ;
1926
- v. insert ( ( span, p_id, p_name, res) ) ;
1927
- param = p_def_id;
1928
- }
1957
+ let p_id = self . resolver . next_node_id ( ) ;
1958
+ let p_def_id = self . resolver . create_def (
1959
+ * parent_def_id,
1960
+ p_id,
1961
+ DefPathData :: LifetimeNs ( kw:: UnderscoreLifetime ) ,
1962
+ ExpnId :: root ( ) ,
1963
+ span. with_parent ( None ) ,
1964
+ ) ;
1965
+
1966
+ let p_name = ParamName :: Fresh ( param) ;
1967
+ v. insert ( ( span, p_id, p_name, res) ) ;
1968
+ param = p_def_id;
1929
1969
}
1930
1970
}
1931
1971
} else if let Some ( introducer) = introducer {
@@ -1948,21 +1988,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1948
1988
} else {
1949
1989
hir:: LifetimeName :: Underscore
1950
1990
} ;
1951
- match & mut self . captured_lifetimes {
1952
- Some ( ( parent_def_id, captures, binders) ) if !binders. contains ( & binder) => {
1953
- let p_id = self . resolver . next_node_id ( ) ;
1954
- let p_def_id = self . resolver . create_def (
1955
- * parent_def_id,
1956
- p_id,
1957
- DefPathData :: LifetimeNs ( kw:: UnderscoreLifetime ) ,
1958
- ExpnId :: root ( ) ,
1959
- span. with_parent ( None ) ,
1960
- ) ;
1961
- let p_name = ParamName :: Fresh ( p_def_id) ;
1962
- captures. insert ( p_def_id, ( span, p_id, p_name, res) ) ;
1963
- hir:: LifetimeName :: Param ( p_name)
1964
- }
1965
- _ => l_name,
1991
+ if let Some ( LifetimeCaptureContext { parent_def_id, captures, binders_to_ignore } ) =
1992
+ & mut self . captured_lifetimes
1993
+ && !binders_to_ignore. contains ( & binder)
1994
+ {
1995
+ let p_id = self . resolver . next_node_id ( ) ;
1996
+ let p_def_id = self . resolver . create_def (
1997
+ * parent_def_id,
1998
+ p_id,
1999
+ DefPathData :: LifetimeNs ( kw:: UnderscoreLifetime ) ,
2000
+ ExpnId :: root ( ) ,
2001
+ span. with_parent ( None ) ,
2002
+ ) ;
2003
+ let p_name = ParamName :: Fresh ( p_def_id) ;
2004
+ captures. insert ( p_def_id, ( span, p_id, p_name, res) ) ;
2005
+ hir:: LifetimeName :: Param ( p_name)
2006
+ } else {
2007
+ l_name
1966
2008
}
1967
2009
}
1968
2010
LifetimeRes :: Static => hir:: LifetimeName :: Static ,
@@ -2069,16 +2111,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
2069
2111
self . lower_generic_params ( & p. bound_generic_params , itctx. reborrow ( ) ) ;
2070
2112
2071
2113
let trait_ref = self . with_in_scope_lifetime_defs ( & p. bound_generic_params , |this| {
2072
- if let Some ( ( _, _, binders) ) = & mut this. captured_lifetimes {
2073
- binders. insert ( p. trait_ref . ref_id ) ;
2074
- }
2075
-
2076
- let trait_ref = this. lower_trait_ref ( & p. trait_ref , itctx. reborrow ( ) ) ;
2077
-
2078
- if let Some ( ( _, _, binders) ) = & mut this. captured_lifetimes {
2079
- binders. remove ( & p. trait_ref . ref_id ) ;
2080
- }
2081
- trait_ref
2114
+ this. with_lifetime_binder ( p. trait_ref . ref_id , |this| {
2115
+ this. lower_trait_ref ( & p. trait_ref , itctx. reborrow ( ) )
2116
+ } )
2082
2117
} ) ;
2083
2118
2084
2119
hir:: PolyTraitRef { bound_generic_params, trait_ref, span : self . lower_span ( p. span ) }
0 commit comments