From cd844c5fb54913bced99a046230e9af7b3704c9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Sat, 31 May 2014 14:21:39 +0200 Subject: [PATCH] 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). --- src/librustc/middle/typeck/check/method.rs | 44 +++++----------------- 1 file changed, 10 insertions(+), 34 deletions(-) diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index ec2fa0dab55..dcba3a22b70 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -1026,13 +1026,7 @@ impl<'a> LookupContext<'a> { fn consider_candidates(&self, rcvr_ty: ty::t, candidates: &[Candidate]) -> Option { - // FIXME(pcwalton): Do we need to clone here? - let relevant_candidates: Vec = - 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()); + let relevant_candidates = self.filter_candidates(rcvr_ty, candidates); if relevant_candidates.len() == 0 { return None; @@ -1069,22 +1063,16 @@ impl<'a> LookupContext<'a> { Some(self.confirm_candidate(rcvr_ty, relevant_candidates.get(0))) } - fn merge_candidates(&self, candidates: &[Candidate]) -> Vec { - let mut merged = Vec::new(); - let mut i = 0; - while i < candidates.len() { - let candidate_a = &candidates[i]; + fn filter_candidates(&self, rcvr_ty: ty::t, candidates: &[Candidate]) -> Vec { + let mut relevant_candidates: Vec = Vec::new(); - let mut skip = false; - - let mut j = i + 1; - while j < candidates.len() { - let candidate_b = &candidates[j]; + for candidate_a in candidates.iter().filter(|&c| self.is_relevant(rcvr_ty, c)) { + // Skip this one if we already have one like it + if !relevant_candidates.iter().any(|candidate_b| { debug!("attempting to merge {} and {}", candidate_a.repr(self.tcx()), candidate_b.repr(self.tcx())); - let candidates_same = match (&candidate_a.origin, - &candidate_b.origin) { + match (&candidate_a.origin, &candidate_b.origin) { (&MethodParam(ref p1), &MethodParam(ref p2)) => { let same_trait = p1.trait_id == p2.trait_id; let same_method = p1.method_num == p2.method_num; @@ -1095,25 +1083,13 @@ impl<'a> LookupContext<'a> { same_trait && same_method && same_param } _ => false - }; - if candidates_same { - skip = true; - break; } - j += 1; - } - - i += 1; - - if skip { - // There are more than one of these and we need only one - continue; - } else { - merged.push(candidate_a.clone()); + }) { + relevant_candidates.push(candidate_a.clone()); } } - return merged; + relevant_candidates } fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)