Remove unnecessary allocations / clones during method lookup
By dropping the intermediate vector that holds the relevant candidates including duplicates and directly building the vector that has the duplicates removed we can eliminate quite a few allocations. This reduces the times for type checking by 5-10% (measured with libstd, libsyntax and librustc).
This commit is contained in:
parent
ff2bf58e9e
commit
cd844c5fb5
@ -1026,13 +1026,7 @@ impl<'a> LookupContext<'a> {
|
|||||||
fn consider_candidates(&self, rcvr_ty: ty::t,
|
fn consider_candidates(&self, rcvr_ty: ty::t,
|
||||||
candidates: &[Candidate])
|
candidates: &[Candidate])
|
||||||
-> Option<MethodCallee> {
|
-> Option<MethodCallee> {
|
||||||
// FIXME(pcwalton): Do we need to clone here?
|
let relevant_candidates = self.filter_candidates(rcvr_ty, candidates);
|
||||||
let relevant_candidates: Vec<Candidate> =
|
|
||||||
candidates.iter().map(|c| (*c).clone()).
|
|
||||||
filter(|c| self.is_relevant(rcvr_ty, c)).collect();
|
|
||||||
|
|
||||||
let relevant_candidates =
|
|
||||||
self.merge_candidates(relevant_candidates.as_slice());
|
|
||||||
|
|
||||||
if relevant_candidates.len() == 0 {
|
if relevant_candidates.len() == 0 {
|
||||||
return None;
|
return None;
|
||||||
@ -1069,22 +1063,16 @@ impl<'a> LookupContext<'a> {
|
|||||||
Some(self.confirm_candidate(rcvr_ty, relevant_candidates.get(0)))
|
Some(self.confirm_candidate(rcvr_ty, relevant_candidates.get(0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merge_candidates(&self, candidates: &[Candidate]) -> Vec<Candidate> {
|
fn filter_candidates(&self, rcvr_ty: ty::t, candidates: &[Candidate]) -> Vec<Candidate> {
|
||||||
let mut merged = Vec::new();
|
let mut relevant_candidates: Vec<Candidate> = Vec::new();
|
||||||
let mut i = 0;
|
|
||||||
while i < candidates.len() {
|
|
||||||
let candidate_a = &candidates[i];
|
|
||||||
|
|
||||||
let mut skip = false;
|
for candidate_a in candidates.iter().filter(|&c| self.is_relevant(rcvr_ty, c)) {
|
||||||
|
// Skip this one if we already have one like it
|
||||||
let mut j = i + 1;
|
if !relevant_candidates.iter().any(|candidate_b| {
|
||||||
while j < candidates.len() {
|
|
||||||
let candidate_b = &candidates[j];
|
|
||||||
debug!("attempting to merge {} and {}",
|
debug!("attempting to merge {} and {}",
|
||||||
candidate_a.repr(self.tcx()),
|
candidate_a.repr(self.tcx()),
|
||||||
candidate_b.repr(self.tcx()));
|
candidate_b.repr(self.tcx()));
|
||||||
let candidates_same = match (&candidate_a.origin,
|
match (&candidate_a.origin, &candidate_b.origin) {
|
||||||
&candidate_b.origin) {
|
|
||||||
(&MethodParam(ref p1), &MethodParam(ref p2)) => {
|
(&MethodParam(ref p1), &MethodParam(ref p2)) => {
|
||||||
let same_trait = p1.trait_id == p2.trait_id;
|
let same_trait = p1.trait_id == p2.trait_id;
|
||||||
let same_method = p1.method_num == p2.method_num;
|
let same_method = p1.method_num == p2.method_num;
|
||||||
@ -1095,25 +1083,13 @@ impl<'a> LookupContext<'a> {
|
|||||||
same_trait && same_method && same_param
|
same_trait && same_method && same_param
|
||||||
}
|
}
|
||||||
_ => false
|
_ => false
|
||||||
};
|
|
||||||
if candidates_same {
|
|
||||||
skip = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
j += 1;
|
}) {
|
||||||
}
|
relevant_candidates.push(candidate_a.clone());
|
||||||
|
|
||||||
i += 1;
|
|
||||||
|
|
||||||
if skip {
|
|
||||||
// There are more than one of these and we need only one
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
merged.push(candidate_a.clone());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return merged;
|
relevant_candidates
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
|
fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
|
||||||
|
Loading…
Reference in New Issue
Block a user