1
- use crate :: Resolver ;
1
+ use crate :: { ImplTraitContext , Resolver } ;
2
2
use rustc_ast:: visit:: { self , FnKind } ;
3
3
use rustc_ast:: walk_list;
4
4
use rustc_ast:: * ;
@@ -16,14 +16,15 @@ crate fn collect_definitions(
16
16
fragment : & AstFragment ,
17
17
expansion : ExpnId ,
18
18
) {
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 } ) ;
21
21
}
22
22
23
23
/// Creates `DefId`s for nodes in the AST.
24
24
struct DefCollector < ' a , ' b > {
25
25
resolver : & ' a mut Resolver < ' b > ,
26
26
parent_def : LocalDefId ,
27
+ impl_trait_context : ImplTraitContext ,
27
28
expansion : ExpnId ,
28
29
}
29
30
@@ -40,6 +41,16 @@ impl<'a, 'b> DefCollector<'a, 'b> {
40
41
self . parent_def = orig_parent_def;
41
42
}
42
43
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
+
43
54
fn collect_field ( & mut self , field : & ' a StructField , index : Option < usize > ) {
44
55
let index = |this : & Self | {
45
56
index. unwrap_or_else ( || {
@@ -60,8 +71,9 @@ impl<'a, 'b> DefCollector<'a, 'b> {
60
71
}
61
72
62
73
fn visit_macro_invoc ( & mut self , id : NodeId ) {
74
+ let id = id. placeholder_to_expn_id ( ) ;
63
75
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 ) ) ;
65
77
assert ! ( old_parent. is_none( ) , "parent `LocalDefId` is reset for an invocation" ) ;
66
78
}
67
79
}
@@ -103,29 +115,37 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
103
115
let def = self . create_def ( i. id , def_data, i. span ) ;
104
116
105
117
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
+ }
111
125
}
126
+ _ => { }
112
127
}
113
- _ => { }
114
- }
115
- visit:: walk_item ( this, i) ;
128
+ visit:: walk_item ( this, i) ;
129
+ } )
116
130
} ) ;
117
131
}
118
132
119
133
fn visit_fn ( & mut self , fn_kind : FnKind < ' a > , span : Span , _: NodeId ) {
120
134
if let FnKind :: Fn ( _, _, sig, _, body) = fn_kind {
121
135
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) ;
123
138
124
139
// For async functions, we need to create their inner defs inside of a
125
140
// closure to match their desugared representation. Besides that,
126
141
// we must mirror everything that `visit::walk_fn` below does.
127
142
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
+ } ) ;
129
149
let closure_def = self . create_def ( closure_id, DefPathData :: ClosureExpr , span) ;
130
150
self . with_parent ( closure_def, |this| walk_list ! ( this, visit_block, body) ) ;
131
151
return ;
@@ -137,6 +157,14 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
137
157
138
158
fn visit_use_tree ( & mut self , use_tree : & ' a UseTree , id : NodeId , _nested : bool ) {
139
159
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
+ }
140
168
visit:: walk_use_tree ( self , use_tree, id) ;
141
169
}
142
170
@@ -191,7 +219,15 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
191
219
} ;
192
220
self . create_def ( param. id , def_path_data, param. ident . span ) ;
193
221
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
+ } ) ;
195
231
}
196
232
197
233
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> {
244
280
match ty. kind {
245
281
TyKind :: MacCall ( ..) => self . visit_macro_invoc ( ty. id ) ,
246
282
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) )
249
296
}
250
297
_ => visit:: walk_ty ( self , ty) ,
251
298
}
@@ -275,7 +322,13 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
275
322
}
276
323
277
324
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
+ }
279
332
}
280
333
281
334
// This method is called only when we are visiting an individual field
0 commit comments