@@ -14,7 +14,7 @@ use astconv::AstConv;
14
14
use check:: { FnCtxt , PlaceOp , callee, Needs } ;
15
15
use hir:: GenericArg ;
16
16
use hir:: def_id:: DefId ;
17
- use rustc:: ty:: subst:: Substs ;
17
+ use rustc:: ty:: subst:: { Kind , Substs } ;
18
18
use rustc:: traits;
19
19
use rustc:: ty:: { self , Ty , GenericParamDefKind } ;
20
20
use rustc:: ty:: subst:: Subst ;
@@ -24,6 +24,8 @@ use rustc::ty::fold::TypeFoldable;
24
24
use rustc:: infer:: { self , InferOk } ;
25
25
use syntax_pos:: Span ;
26
26
use rustc:: hir;
27
+ use rustc_data_structures:: accumulate_vec:: AccumulateVec ;
28
+ use rustc_data_structures:: array_vec:: ArrayVec ;
27
29
28
30
use std:: ops:: Deref ;
29
31
@@ -323,48 +325,86 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
323
325
// parameters from the type and those from the method.
324
326
assert_eq ! ( method_generics. parent_count, parent_substs. len( ) ) ;
325
327
326
- let inferred_lifetimes = if if let Some ( ref data) = segment. args {
327
- !data. args . iter ( ) . any ( |arg| match arg {
328
- GenericArg :: Lifetime ( _) => true ,
329
- _ => false ,
330
- } )
331
- } else {
332
- true
333
- } {
334
- method_generics. own_counts ( ) . lifetimes
328
+ // Collect the segments of the path: we need to substitute arguments
329
+ // for parameters throughout the entire path (wherever there are
330
+ // generic parameters).
331
+ let def_id = pick. item . def_id ;
332
+ let mut parent_defs = self . tcx . generics_of ( def_id) ;
333
+ let count = parent_defs. count ( ) ;
334
+ let mut stack = vec ! [ ( def_id, parent_defs) ] ;
335
+ while let Some ( def_id) = parent_defs. parent {
336
+ parent_defs = self . tcx . generics_of ( def_id) ;
337
+ stack. push ( ( def_id, parent_defs) ) ;
338
+ }
339
+
340
+ // We manually build up the substitution, rather than using convenience
341
+ // methods in subst.rs so that we can iterate over the arguments and
342
+ // parameters in lock-step linearly, rather than trying to match each pair.
343
+ let mut substs: AccumulateVec < [ Kind < ' tcx > ; 8 ] > = if count <= 8 {
344
+ AccumulateVec :: Array ( ArrayVec :: new ( ) )
335
345
} else {
336
- 0
346
+ AccumulateVec :: Heap ( Vec :: with_capacity ( count ) )
337
347
} ;
348
+ fn push_kind < ' tcx > ( substs : & mut AccumulateVec < [ Kind < ' tcx > ; 8 ] > , kind : Kind < ' tcx > ) {
349
+ match substs {
350
+ AccumulateVec :: Array ( ref mut arr) => arr. push ( kind) ,
351
+ AccumulateVec :: Heap ( ref mut vec) => vec. push ( kind) ,
352
+ }
353
+ }
338
354
339
- Substs :: for_item ( self . tcx , pick. item . def_id , |param, _| {
340
- let param_idx = param. index as usize ;
341
- if param_idx < parent_substs. len ( ) {
342
- parent_substs[ param_idx]
343
- } else {
344
- let param_idx = ( param. index as usize - parent_substs. len ( ) )
345
- . saturating_sub ( inferred_lifetimes) ;
355
+ // Iterate over each segment of the path.
356
+ while let Some ( ( _, defs) ) = stack. pop ( ) {
357
+ let mut params = defs. params . iter ( ) ;
358
+ let mut next_param = params. next ( ) ;
359
+
360
+ while let Some ( param) = next_param {
361
+ if let Some ( & kind) = parent_substs. get ( param. index as usize ) {
362
+ push_kind ( & mut substs, kind) ;
363
+ next_param = params. next ( ) ;
364
+ } else {
365
+ break ;
366
+ }
367
+ }
346
368
347
- if let Some ( ref data) = segment. args {
348
- if let Some ( arg) = data. args . get ( param_idx) {
369
+ if let Some ( ref data) = segment. args {
370
+ let args = & data. args ;
371
+ ' args: for arg in args {
372
+ while let Some ( param) = next_param {
349
373
match param. kind {
350
374
GenericParamDefKind :: Lifetime => match arg {
351
375
GenericArg :: Lifetime ( lt) => {
352
- return AstConv :: ast_region_to_region (
353
- self . fcx , lt, Some ( param) ) . into ( ) ;
376
+ push_kind ( & mut substs, AstConv :: ast_region_to_region (
377
+ self . fcx , lt, Some ( param) ) . into ( ) ) ;
378
+ next_param = params. next ( ) ;
379
+ continue ' args;
380
+ }
381
+ _ => {
382
+ push_kind ( & mut substs, self . var_for_def ( self . span , param) ) ;
383
+ next_param = params. next ( ) ;
354
384
}
355
- _ => { }
356
385
}
357
386
GenericParamDefKind :: Type { .. } => match arg {
358
- GenericArg :: Type ( ty) => return self . to_ty ( ty) . into ( ) ,
359
- _ => { }
387
+ GenericArg :: Type ( ty) => {
388
+ push_kind ( & mut substs, self . to_ty ( ty) . into ( ) ) ;
389
+ next_param = params. next ( ) ;
390
+ continue ' args;
391
+ }
392
+ _ => {
393
+ break ' args;
394
+ }
360
395
}
361
396
}
362
397
}
363
398
}
399
+ }
364
400
365
- self . var_for_def ( self . span , param)
401
+ while let Some ( param) = next_param {
402
+ push_kind ( & mut substs, self . var_for_def ( self . span , param) ) ;
403
+ next_param = params. next ( ) ;
366
404
}
367
- } )
405
+ }
406
+
407
+ self . tcx . intern_substs ( & substs)
368
408
}
369
409
370
410
fn unify_receivers ( & mut self , self_ty : Ty < ' tcx > , method_self_ty : Ty < ' tcx > ) {
0 commit comments