41
41
// in the HIR, especially for multiple identifiers.
42
42
43
43
use hir;
44
- use hir:: map:: Definitions ;
44
+ use hir:: map:: { Definitions , DefKey } ;
45
45
use hir:: map:: definitions:: DefPathData ;
46
46
use hir:: def_id:: { DefIndex , DefId } ;
47
47
use hir:: def:: { Def , PathResolution } ;
48
48
use session:: Session ;
49
- use util:: nodemap:: { NodeMap , FxHashMap } ;
49
+ use util:: nodemap:: { DefIdMap , NodeMap , FxHashMap } ;
50
50
51
51
use std:: collections:: BTreeMap ;
52
52
use std:: iter;
@@ -78,6 +78,8 @@ pub struct LoweringContext<'a> {
78
78
trait_items : BTreeMap < hir:: TraitItemId , hir:: TraitItem > ,
79
79
impl_items : BTreeMap < hir:: ImplItemId , hir:: ImplItem > ,
80
80
bodies : FxHashMap < hir:: BodyId , hir:: Body > ,
81
+
82
+ type_def_lifetime_params : DefIdMap < usize > ,
81
83
}
82
84
83
85
pub trait Resolver {
@@ -110,6 +112,7 @@ pub fn lower_crate(sess: &Session,
110
112
trait_items : BTreeMap :: new ( ) ,
111
113
impl_items : BTreeMap :: new ( ) ,
112
114
bodies : FxHashMap ( ) ,
115
+ type_def_lifetime_params : DefIdMap ( ) ,
113
116
} . lower_crate ( krate)
114
117
}
115
118
@@ -123,24 +126,33 @@ enum ParamMode {
123
126
124
127
impl < ' a > LoweringContext < ' a > {
125
128
fn lower_crate ( mut self , c : & Crate ) -> hir:: Crate {
126
- self . lower_items ( c) ;
127
- let module = self . lower_mod ( & c. module ) ;
128
- let attrs = self . lower_attrs ( & c. attrs ) ;
129
- let exported_macros = c. exported_macros . iter ( ) . map ( |m| self . lower_macro_def ( m) ) . collect ( ) ;
129
+ /// Full-crate AST visitor that inserts into a fresh
130
+ /// `LoweringContext` any information that may be
131
+ /// needed from arbitrary locations in the crate.
132
+ /// E.g. The number of lifetime generic parameters
133
+ /// declared for every type and trait definition.
134
+ struct MiscCollector < ' lcx , ' interner : ' lcx > {
135
+ lctx : & ' lcx mut LoweringContext < ' interner > ,
136
+ }
130
137
131
- hir:: Crate {
132
- module : module,
133
- attrs : attrs,
134
- span : c. span ,
135
- exported_macros : exported_macros,
136
- items : self . items ,
137
- trait_items : self . trait_items ,
138
- impl_items : self . impl_items ,
139
- bodies : self . bodies ,
138
+ impl < ' lcx , ' interner > Visitor < ' lcx > for MiscCollector < ' lcx , ' interner > {
139
+ fn visit_item ( & mut self , item : & ' lcx Item ) {
140
+ match item. node {
141
+ ItemKind :: Struct ( _, ref generics) |
142
+ ItemKind :: Union ( _, ref generics) |
143
+ ItemKind :: Enum ( _, ref generics) |
144
+ ItemKind :: Ty ( _, ref generics) |
145
+ ItemKind :: Trait ( _, ref generics, ..) => {
146
+ let def_id = self . lctx . resolver . definitions ( ) . local_def_id ( item. id ) ;
147
+ let count = generics. lifetimes . len ( ) ;
148
+ self . lctx . type_def_lifetime_params . insert ( def_id, count) ;
149
+ }
150
+ _ => { }
151
+ }
152
+ visit:: walk_item ( self , item) ;
153
+ }
140
154
}
141
- }
142
155
143
- fn lower_items ( & mut self , c : & Crate ) {
144
156
struct ItemLowerer < ' lcx , ' interner : ' lcx > {
145
157
lctx : & ' lcx mut LoweringContext < ' interner > ,
146
158
}
@@ -167,8 +179,23 @@ impl<'a> LoweringContext<'a> {
167
179
}
168
180
}
169
181
170
- let mut item_lowerer = ItemLowerer { lctx : self } ;
171
- visit:: walk_crate ( & mut item_lowerer, c) ;
182
+ visit:: walk_crate ( & mut MiscCollector { lctx : & mut self } , c) ;
183
+ visit:: walk_crate ( & mut ItemLowerer { lctx : & mut self } , c) ;
184
+
185
+ let module = self . lower_mod ( & c. module ) ;
186
+ let attrs = self . lower_attrs ( & c. attrs ) ;
187
+ let exported_macros = c. exported_macros . iter ( ) . map ( |m| self . lower_macro_def ( m) ) . collect ( ) ;
188
+
189
+ hir:: Crate {
190
+ module : module,
191
+ attrs : attrs,
192
+ span : c. span ,
193
+ exported_macros : exported_macros,
194
+ items : self . items ,
195
+ trait_items : self . trait_items ,
196
+ impl_items : self . impl_items ,
197
+ bodies : self . bodies ,
198
+ }
172
199
}
173
200
174
201
fn record_body ( & mut self , value : hir:: Expr , decl : Option < & FnDecl > )
@@ -232,6 +259,14 @@ impl<'a> LoweringContext<'a> {
232
259
result
233
260
}
234
261
262
+ fn def_key ( & mut self , id : DefId ) -> DefKey {
263
+ if id. is_local ( ) {
264
+ self . resolver . definitions ( ) . def_key ( id. index )
265
+ } else {
266
+ self . sess . cstore . def_key ( id)
267
+ }
268
+ }
269
+
235
270
fn lower_opt_sp_ident ( & mut self , o_id : Option < Spanned < Ident > > ) -> Option < Spanned < Name > > {
236
271
o_id. map ( |sp_ident| respan ( sp_ident. span , sp_ident. node . name ) )
237
272
}
@@ -279,7 +314,11 @@ impl<'a> LoweringContext<'a> {
279
314
TyKind :: Slice ( ref ty) => hir:: TySlice ( self . lower_ty ( ty) ) ,
280
315
TyKind :: Ptr ( ref mt) => hir:: TyPtr ( self . lower_mt ( mt) ) ,
281
316
TyKind :: Rptr ( ref region, ref mt) => {
282
- hir:: TyRptr ( self . lower_opt_lifetime ( region) , self . lower_mt ( mt) )
317
+ let lifetime = match * region {
318
+ Some ( ref lt) => self . lower_lifetime ( lt) ,
319
+ None => self . elided_lifetime ( t. span )
320
+ } ;
321
+ hir:: TyRptr ( lifetime, self . lower_mt ( mt) )
283
322
}
284
323
TyKind :: BareFn ( ref f) => {
285
324
hir:: TyBareFn ( P ( hir:: BareFnTy {
@@ -377,7 +416,40 @@ impl<'a> LoweringContext<'a> {
377
416
}
378
417
_ => param_mode
379
418
} ;
380
- self . lower_path_segment ( segment, param_mode)
419
+
420
+ // Figure out if this is a type/trait segment,
421
+ // which may need lifetime elision performed.
422
+ let parent_def_id = |this : & mut Self , def_id : DefId | {
423
+ DefId {
424
+ krate : def_id. krate ,
425
+ index : this. def_key ( def_id) . parent . expect ( "missing parent" )
426
+ }
427
+ } ;
428
+ let type_def_id = match resolution. base_def {
429
+ Def :: AssociatedTy ( def_id) if i + 2 == proj_start => {
430
+ Some ( parent_def_id ( self , def_id) )
431
+ }
432
+ Def :: Variant ( def_id) if i + 1 == proj_start => {
433
+ Some ( parent_def_id ( self , def_id) )
434
+ }
435
+ Def :: Struct ( def_id) |
436
+ Def :: Union ( def_id) |
437
+ Def :: Enum ( def_id) |
438
+ Def :: TyAlias ( def_id) |
439
+ Def :: Trait ( def_id) if i + 1 == proj_start => Some ( def_id) ,
440
+ _ => None
441
+ } ;
442
+
443
+ let num_lifetimes = type_def_id. map_or ( 0 , |def_id| {
444
+ if let Some ( & n) = self . type_def_lifetime_params . get ( & def_id) {
445
+ return n;
446
+ }
447
+ assert ! ( !def_id. is_local( ) ) ;
448
+ let ( n, _) = self . sess . cstore . item_generics_own_param_counts ( def_id) ;
449
+ self . type_def_lifetime_params . insert ( def_id, n) ;
450
+ n
451
+ } ) ;
452
+ self . lower_path_segment ( p. span , segment, param_mode, num_lifetimes)
381
453
} ) . collect ( ) ,
382
454
span : p. span ,
383
455
} ) ;
@@ -411,7 +483,7 @@ impl<'a> LoweringContext<'a> {
411
483
// 3. `<<std::vec::Vec<T>>::IntoIter>::Item`
412
484
// * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
413
485
for ( i, segment) in p. segments . iter ( ) . enumerate ( ) . skip ( proj_start) {
414
- let segment = P ( self . lower_path_segment ( segment, param_mode) ) ;
486
+ let segment = P ( self . lower_path_segment ( p . span , segment, param_mode, 0 ) ) ;
415
487
let qpath = hir:: QPath :: TypeRelative ( ty, segment) ;
416
488
417
489
// It's finished, return the extension of the right node type.
@@ -443,7 +515,7 @@ impl<'a> LoweringContext<'a> {
443
515
hir:: Path {
444
516
def : self . expect_full_def ( id) ,
445
517
segments : segments. map ( |segment| {
446
- self . lower_path_segment ( segment, param_mode)
518
+ self . lower_path_segment ( p . span , segment, param_mode, 0 )
447
519
} ) . chain ( name. map ( |name| {
448
520
hir:: PathSegment {
449
521
name : name,
@@ -464,10 +536,12 @@ impl<'a> LoweringContext<'a> {
464
536
}
465
537
466
538
fn lower_path_segment ( & mut self ,
539
+ path_span : Span ,
467
540
segment : & PathSegment ,
468
- param_mode : ParamMode )
541
+ param_mode : ParamMode ,
542
+ expected_lifetimes : usize )
469
543
-> hir:: PathSegment {
470
- let parameters = if let Some ( ref parameters) = segment. parameters {
544
+ let mut parameters = if let Some ( ref parameters) = segment. parameters {
471
545
match * * parameters {
472
546
PathParameters :: AngleBracketed ( ref data) => {
473
547
let data = self . lower_angle_bracketed_parameter_data ( data, param_mode) ;
@@ -482,6 +556,14 @@ impl<'a> LoweringContext<'a> {
482
556
hir:: AngleBracketedParameters ( data)
483
557
} ;
484
558
559
+ if let hir:: AngleBracketedParameters ( ref mut data) = parameters {
560
+ if data. lifetimes . is_empty ( ) {
561
+ data. lifetimes = ( 0 ..expected_lifetimes) . map ( |_| {
562
+ self . elided_lifetime ( path_span)
563
+ } ) . collect ( ) ;
564
+ }
565
+ }
566
+
485
567
hir:: PathSegment {
486
568
name : segment. identifier . name ,
487
569
parameters : parameters,
@@ -628,10 +710,6 @@ impl<'a> LoweringContext<'a> {
628
710
lts. iter ( ) . map ( |l| self . lower_lifetime_def ( l) ) . collect ( )
629
711
}
630
712
631
- fn lower_opt_lifetime ( & mut self , o_lt : & Option < Lifetime > ) -> Option < hir:: Lifetime > {
632
- o_lt. as_ref ( ) . map ( |lt| self . lower_lifetime ( lt) )
633
- }
634
-
635
713
fn lower_generics ( & mut self , g : & Generics ) -> hir:: Generics {
636
714
// Collect `?Trait` bounds in where clause and move them to parameter definitions.
637
715
let mut add_bounds = NodeMap ( ) ;
@@ -751,8 +829,12 @@ impl<'a> LoweringContext<'a> {
751
829
}
752
830
753
831
fn lower_trait_ref ( & mut self , p : & TraitRef ) -> hir:: TraitRef {
832
+ let path = match self . lower_qpath ( p. ref_id , & None , & p. path , ParamMode :: Explicit ) {
833
+ hir:: QPath :: Resolved ( None , path) => path. and_then ( |path| path) ,
834
+ qpath => bug ! ( "lower_trait_ref: unexpected QPath `{:?}`" , qpath)
835
+ } ;
754
836
hir:: TraitRef {
755
- path : self . lower_path ( p . ref_id , & p . path , ParamMode :: Explicit , false ) ,
837
+ path : path,
756
838
ref_id : p. ref_id ,
757
839
}
758
840
}
@@ -2276,4 +2358,12 @@ impl<'a> LoweringContext<'a> {
2276
2358
span : span,
2277
2359
} )
2278
2360
}
2361
+
2362
+ fn elided_lifetime ( & mut self , span : Span ) -> hir:: Lifetime {
2363
+ hir:: Lifetime {
2364
+ id : self . next_id ( ) ,
2365
+ span : span,
2366
+ name : keywords:: Invalid . name ( )
2367
+ }
2368
+ }
2279
2369
}
0 commit comments