From 4acdc524fb73347763d7e05d40cbb0d4f3e48ece Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Tue, 24 Nov 2015 17:19:39 +0900 Subject: [PATCH] Track trait import to method resolution --- src/librustc/middle/ty/mod.rs | 7 ++++- src/librustc_resolve/lib.rs | 20 ++++++++----- src/librustc_typeck/check/method/probe.rs | 35 +++++++++++++++++------ 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/src/librustc/middle/ty/mod.rs b/src/librustc/middle/ty/mod.rs index ca9f8881ed95c..5dc539ea882c7 100644 --- a/src/librustc/middle/ty/mod.rs +++ b/src/librustc/middle/ty/mod.rs @@ -2751,8 +2751,13 @@ pub type FreevarMap = NodeMap>; pub type CaptureModeMap = NodeMap; +pub struct TraitCandidate { + pub def_id: DefId, + pub import_id: Option, +} + // Trait method resolution -pub type TraitMap = NodeMap>; +pub type TraitMap = NodeMap>; // Map from the NodeId of a glob import to a list of items which are actually // imported. diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 659c46fbb178d..26047b6835f87 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -60,7 +60,7 @@ use rustc::middle::def_id::DefId; use rustc::middle::pat_util::pat_bindings; use rustc::middle::privacy::*; use rustc::middle::subst::{ParamSpace, FnSpace, TypeSpace}; -use rustc::middle::ty::{Freevar, FreevarMap, TraitMap, GlobMap}; +use rustc::middle::ty::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; use rustc::util::nodemap::{NodeMap, DefIdSet, FnvHashMap}; use syntax::ast; @@ -3608,14 +3608,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn get_traits_containing_item(&mut self, name: Name) -> Vec { + fn get_traits_containing_item(&mut self, name: Name) -> Vec { debug!("(getting traits containing item) looking for '{}'", name); - fn add_trait_info(found_traits: &mut Vec, trait_def_id: DefId, name: Name) { + fn add_trait_info(found_traits: &mut Vec, + trait_def_id: DefId, + import_id: Option, + name: Name) { debug!("(adding trait info) found trait {:?} for method '{}'", trait_def_id, name); - found_traits.push(trait_def_id); + found_traits.push(TraitCandidate { + def_id: trait_def_id, + import_id: import_id, + }); } let mut found_traits = Vec::new(); @@ -3625,7 +3631,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match self.current_trait_ref { Some((trait_def_id, _)) => { if self.trait_item_map.contains_key(&(name, trait_def_id)) { - add_trait_info(&mut found_traits, trait_def_id, name); + add_trait_info(&mut found_traits, trait_def_id, None, name); } } None => {} // Nothing to do. @@ -3645,7 +3651,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { _ => continue, }; if self.trait_item_map.contains_key(&(name, trait_def_id)) { - add_trait_info(&mut found_traits, trait_def_id, name); + add_trait_info(&mut found_traits, trait_def_id, None, name); } } } @@ -3661,8 +3667,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(..) | None => continue, }; if self.trait_item_map.contains_key(&(name, did)) { - add_trait_info(&mut found_traits, did, name); let id = import.type_ns.id; + add_trait_info(&mut found_traits, did, Some(id), name); self.used_imports.insert((id, TypeNS)); let trait_name = self.get_trait_name(did); self.record_import_use(id, trait_name); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index ed819d46041e6..1ee7c0bf97c53 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -44,6 +44,7 @@ struct ProbeContext<'a, 'tcx:'a> { inherent_candidates: Vec>, extension_candidates: Vec>, impl_dups: HashSet, + import_id: Option, /// Collects near misses when the candidate functions are missing a `self` keyword and is only /// used for error reporting @@ -66,6 +67,7 @@ struct Candidate<'tcx> { xform_self_ty: Ty<'tcx>, item: ty::ImplOrTraitItem<'tcx>, kind: CandidateKind<'tcx>, + import_id: Option, } #[derive(Debug)] @@ -83,6 +85,7 @@ enum CandidateKind<'tcx> { pub struct Pick<'tcx> { pub item: ty::ImplOrTraitItem<'tcx>, pub kind: PickKind<'tcx>, + pub import_id: Option, // Indicates that the source expression should be autoderef'd N times // @@ -246,6 +249,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { inherent_candidates: Vec::new(), extension_candidates: Vec::new(), impl_dups: HashSet::new(), + import_id: None, steps: Rc::new(steps), opt_simplified_steps: opt_simplified_steps, static_candidates: Vec::new(), @@ -427,7 +431,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { self.inherent_candidates.push(Candidate { xform_self_ty: xform_self_ty, item: item, - kind: InherentImplCandidate(impl_substs, obligations) + kind: InherentImplCandidate(impl_substs, obligations), + import_id: self.import_id, }); } @@ -455,7 +460,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { this.inherent_candidates.push(Candidate { xform_self_ty: xform_self_ty, item: item, - kind: ObjectCandidate + kind: ObjectCandidate, + import_id: this.import_id, }); }); } @@ -524,7 +530,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { this.inherent_candidates.push(Candidate { xform_self_ty: xform_self_ty, item: item, - kind: WhereClauseCandidate(poly_trait_ref) + kind: WhereClauseCandidate(poly_trait_ref), + import_id: this.import_id, }); }); } @@ -568,9 +575,13 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { let mut duplicates = HashSet::new(); let opt_applicable_traits = self.fcx.ccx.trait_map.get(&expr_id); if let Some(applicable_traits) = opt_applicable_traits { - for &trait_did in applicable_traits { + for trait_candidate in applicable_traits { + let trait_did = trait_candidate.def_id; if duplicates.insert(trait_did) { - try!(self.assemble_extension_candidates_for_trait(trait_did)); + self.import_id = trait_candidate.import_id; + let result = self.assemble_extension_candidates_for_trait(trait_did); + self.import_id = None; + try!(result); } } } @@ -670,7 +681,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { self.extension_candidates.push(Candidate { xform_self_ty: xform_self_ty, item: item.clone(), - kind: ExtensionImplCandidate(impl_def_id, impl_substs, obligations) + kind: ExtensionImplCandidate(impl_def_id, impl_substs, obligations), + import_id: self.import_id, }); }); } @@ -745,7 +757,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { self.inherent_candidates.push(Candidate { xform_self_ty: xform_self_ty, item: item.clone(), - kind: TraitCandidate + kind: TraitCandidate, + import_id: self.import_id, }); } @@ -802,7 +815,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { self.extension_candidates.push(Candidate { xform_self_ty: xform_self_ty, item: item.clone(), - kind: TraitCandidate + kind: TraitCandidate, + import_id: self.import_id, }); } } @@ -833,7 +847,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { self.extension_candidates.push(Candidate { xform_self_ty: xform_self_ty, item: item.clone(), - kind: WhereClauseCandidate(poly_bound) + kind: WhereClauseCandidate(poly_bound), + import_id: self.import_id, }); } } @@ -1126,6 +1141,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { Some(Pick { item: probes[0].item.clone(), kind: TraitPick, + import_id: probes[0].import_id, autoderefs: 0, autoref: None, unsize: None @@ -1329,6 +1345,7 @@ impl<'tcx> Candidate<'tcx> { WhereClausePick(trait_ref.clone()) } }, + import_id: self.import_id, autoderefs: 0, autoref: None, unsize: None