Skip to content

Commit 5d07db4

Browse files
committed
Refactor confirm.rs (part ii)
1 parent 08d49a6 commit 5d07db4

File tree

1 file changed

+67
-27
lines changed

1 file changed

+67
-27
lines changed

src/librustc_typeck/check/method/confirm.rs

Lines changed: 67 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use astconv::AstConv;
1414
use check::{FnCtxt, PlaceOp, callee, Needs};
1515
use hir::GenericArg;
1616
use hir::def_id::DefId;
17-
use rustc::ty::subst::Substs;
17+
use rustc::ty::subst::{Kind, Substs};
1818
use rustc::traits;
1919
use rustc::ty::{self, Ty, GenericParamDefKind};
2020
use rustc::ty::subst::Subst;
@@ -24,6 +24,8 @@ use rustc::ty::fold::TypeFoldable;
2424
use rustc::infer::{self, InferOk};
2525
use syntax_pos::Span;
2626
use rustc::hir;
27+
use rustc_data_structures::accumulate_vec::AccumulateVec;
28+
use rustc_data_structures::array_vec::ArrayVec;
2729

2830
use std::ops::Deref;
2931

@@ -323,48 +325,86 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
323325
// parameters from the type and those from the method.
324326
assert_eq!(method_generics.parent_count, parent_substs.len());
325327

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())
335345
} else {
336-
0
346+
AccumulateVec::Heap(Vec::with_capacity(count))
337347
};
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+
}
338354

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+
}
346368

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 {
349373
match param.kind {
350374
GenericParamDefKind::Lifetime => match arg {
351375
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();
354384
}
355-
_ => {}
356385
}
357386
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+
}
360395
}
361396
}
362397
}
363398
}
399+
}
364400

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();
366404
}
367-
})
405+
}
406+
407+
self.tcx.intern_substs(&substs)
368408
}
369409

370410
fn unify_receivers(&mut self, self_ty: Ty<'tcx>, method_self_ty: Ty<'tcx>) {

0 commit comments

Comments
 (0)