1- use crate :: Resolver ;
1+ use crate :: { ImplTraitContext , Resolver } ;
22use rustc_ast:: visit:: { self , FnKind } ;
33use rustc_ast:: walk_list;
44use rustc_ast:: * ;
@@ -16,14 +16,15 @@ crate fn collect_definitions(
1616 fragment : & AstFragment ,
1717 expansion : ExpnId ,
1818) {
19- let parent_def = resolver. invocation_parents [ & expansion] ;
20- fragment. visit_with ( & mut DefCollector { resolver, parent_def, expansion } ) ;
19+ let ( parent_def, impl_trait_context ) = resolver. invocation_parents [ & expansion] ;
20+ fragment. visit_with ( & mut DefCollector { resolver, parent_def, expansion, impl_trait_context } ) ;
2121}
2222
2323/// Creates `DefId`s for nodes in the AST.
2424struct DefCollector < ' a , ' b > {
2525 resolver : & ' a mut Resolver < ' b > ,
2626 parent_def : LocalDefId ,
27+ impl_trait_context : ImplTraitContext ,
2728 expansion : ExpnId ,
2829}
2930
@@ -40,6 +41,16 @@ impl<'a, 'b> DefCollector<'a, 'b> {
4041 self . parent_def = orig_parent_def;
4142 }
4243
44+ fn with_impl_trait < F : FnOnce ( & mut Self ) > (
45+ & mut self ,
46+ impl_trait_context : ImplTraitContext ,
47+ f : F ,
48+ ) {
49+ let orig_itc = std:: mem:: replace ( & mut self . impl_trait_context , impl_trait_context) ;
50+ f ( self ) ;
51+ self . impl_trait_context = orig_itc;
52+ }
53+
4354 fn collect_field ( & mut self , field : & ' a StructField , index : Option < usize > ) {
4455 let index = |this : & Self | {
4556 index. unwrap_or_else ( || {
@@ -60,8 +71,9 @@ impl<'a, 'b> DefCollector<'a, 'b> {
6071 }
6172
6273 fn visit_macro_invoc ( & mut self , id : NodeId ) {
74+ let id = id. placeholder_to_expn_id ( ) ;
6375 let old_parent =
64- self . resolver . invocation_parents . insert ( id. placeholder_to_expn_id ( ) , self . parent_def ) ;
76+ self . resolver . invocation_parents . insert ( id, ( self . parent_def , self . impl_trait_context ) ) ;
6577 assert ! ( old_parent. is_none( ) , "parent `LocalDefId` is reset for an invocation" ) ;
6678 }
6779}
@@ -103,29 +115,37 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
103115 let def = self . create_def ( i. id , def_data, i. span ) ;
104116
105117 self . with_parent ( def, |this| {
106- match i. kind {
107- ItemKind :: Struct ( ref struct_def, _) | ItemKind :: Union ( ref struct_def, _) => {
108- // If this is a unit or tuple-like struct, register the constructor.
109- if let Some ( ctor_hir_id) = struct_def. ctor_id ( ) {
110- this. create_def ( ctor_hir_id, DefPathData :: Ctor , i. span ) ;
118+ this. with_impl_trait ( ImplTraitContext :: Existential , |this| {
119+ match i. kind {
120+ ItemKind :: Struct ( ref struct_def, _) | ItemKind :: Union ( ref struct_def, _) => {
121+ // If this is a unit or tuple-like struct, register the constructor.
122+ if let Some ( ctor_hir_id) = struct_def. ctor_id ( ) {
123+ this. create_def ( ctor_hir_id, DefPathData :: Ctor , i. span ) ;
124+ }
111125 }
126+ _ => { }
112127 }
113- _ => { }
114- }
115- visit:: walk_item ( this, i) ;
128+ visit:: walk_item ( this, i) ;
129+ } )
116130 } ) ;
117131 }
118132
119133 fn visit_fn ( & mut self , fn_kind : FnKind < ' a > , span : Span , _: NodeId ) {
120134 if let FnKind :: Fn ( _, _, sig, _, body) = fn_kind {
121135 if let Async :: Yes { closure_id, return_impl_trait_id, .. } = sig. header . asyncness {
122- self . create_def ( return_impl_trait_id, DefPathData :: ImplTrait , span) ;
136+ let return_impl_trait_id =
137+ self . create_def ( return_impl_trait_id, DefPathData :: ImplTrait , span) ;
123138
124139 // For async functions, we need to create their inner defs inside of a
125140 // closure to match their desugared representation. Besides that,
126141 // we must mirror everything that `visit::walk_fn` below does.
127142 self . visit_fn_header ( & sig. header ) ;
128- visit:: walk_fn_decl ( self , & sig. decl ) ;
143+ for param in & sig. decl . inputs {
144+ self . visit_param ( param) ;
145+ }
146+ self . with_parent ( return_impl_trait_id, |this| {
147+ this. visit_fn_ret_ty ( & sig. decl . output )
148+ } ) ;
129149 let closure_def = self . create_def ( closure_id, DefPathData :: ClosureExpr , span) ;
130150 self . with_parent ( closure_def, |this| walk_list ! ( this, visit_block, body) ) ;
131151 return ;
@@ -137,6 +157,14 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
137157
138158 fn visit_use_tree ( & mut self , use_tree : & ' a UseTree , id : NodeId , _nested : bool ) {
139159 self . create_def ( id, DefPathData :: Misc , use_tree. span ) ;
160+ match use_tree. kind {
161+ UseTreeKind :: Simple ( _, id1, id2) => {
162+ self . create_def ( id1, DefPathData :: Misc , use_tree. prefix . span ) ;
163+ self . create_def ( id2, DefPathData :: Misc , use_tree. prefix . span ) ;
164+ }
165+ UseTreeKind :: Glob => ( ) ,
166+ UseTreeKind :: Nested ( ..) => { }
167+ }
140168 visit:: walk_use_tree ( self , use_tree, id) ;
141169 }
142170
@@ -191,7 +219,15 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
191219 } ;
192220 self . create_def ( param. id , def_path_data, param. ident . span ) ;
193221
194- visit:: walk_generic_param ( self , param) ;
222+ // impl-Trait can happen inside generic parameters, like
223+ // ```
224+ // fn foo<U: Iterator<Item = impl Clone>>() {}
225+ // ```
226+ //
227+ // In that case, the impl-trait is lowered as an additional generic parameter.
228+ self . with_impl_trait ( ImplTraitContext :: Universal ( self . parent_def ) , |this| {
229+ visit:: walk_generic_param ( this, param)
230+ } ) ;
195231 }
196232
197233 fn visit_assoc_item ( & mut self , i : & ' a AssocItem , ctxt : visit:: AssocCtxt ) {
@@ -244,8 +280,19 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
244280 match ty. kind {
245281 TyKind :: MacCall ( ..) => self . visit_macro_invoc ( ty. id ) ,
246282 TyKind :: ImplTrait ( node_id, _) => {
247- let parent_def = self . create_def ( node_id, DefPathData :: ImplTrait , ty. span ) ;
248- self . with_parent ( parent_def, |this| visit:: walk_ty ( this, ty) ) ;
283+ let parent_def = match self . impl_trait_context {
284+ ImplTraitContext :: Universal ( item_def) => self . resolver . create_def (
285+ item_def,
286+ node_id,
287+ DefPathData :: ImplTrait ,
288+ self . expansion ,
289+ ty. span ,
290+ ) ,
291+ ImplTraitContext :: Existential => {
292+ self . create_def ( node_id, DefPathData :: ImplTrait , ty. span )
293+ }
294+ } ;
295+ self . with_parent ( parent_def, |this| visit:: walk_ty ( this, ty) )
249296 }
250297 _ => visit:: walk_ty ( self , ty) ,
251298 }
@@ -275,7 +322,13 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
275322 }
276323
277324 fn visit_param ( & mut self , p : & ' a Param ) {
278- if p. is_placeholder { self . visit_macro_invoc ( p. id ) } else { visit:: walk_param ( self , p) }
325+ if p. is_placeholder {
326+ self . visit_macro_invoc ( p. id )
327+ } else {
328+ self . with_impl_trait ( ImplTraitContext :: Universal ( self . parent_def ) , |this| {
329+ visit:: walk_param ( this, p)
330+ } )
331+ }
279332 }
280333
281334 // This method is called only when we are visiting an individual field
0 commit comments