Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speed up the lookup of traits implementing a given method #6646

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/libcore/hashmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,9 +303,9 @@ impl<K:Hash + Eq,V> Map<K, V> for HashMap<K, V> {

/// Visit all key-value pairs
fn each<'a>(&'a self, blk: &fn(&K, &'a V) -> bool) -> bool {
for uint::range(0, self.buckets.len()) |i| {
for self.buckets[i].each |bucket| {
if !blk(&bucket.key, &bucket.value) {
for self.buckets.each |bucket| {
for bucket.each |pair| {
if !blk(&pair.key, &pair.value) {
return false;
}
}
Expand Down
185 changes: 97 additions & 88 deletions src/librustc/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,7 @@ pub fn Resolver(session: Session,

graph_root: graph_root,

trait_info: HashMap::new(),
method_map: @mut HashMap::new(),
structs: HashSet::new(),

unresolved_imports: 0,
Expand Down Expand Up @@ -776,7 +776,7 @@ pub struct Resolver {

graph_root: @mut NameBindings,

trait_info: HashMap<def_id, HashSet<ident>>,
method_map: @mut HashMap<ident, HashSet<def_id>>,
structs: HashSet<def_id>,

// The number of imports that are currently unresolved.
Expand Down Expand Up @@ -1292,7 +1292,15 @@ pub impl Resolver {
}

let def_id = local_def(item.id);
self.trait_info.insert(def_id, method_names);
for method_names.each |name| {
if !self.method_map.contains_key(name) {
self.method_map.insert(*name, HashSet::new());
}
match self.method_map.find_mut(name) {
Some(s) => { s.insert(def_id); },
_ => fail!("Can't happen"),
}
}

name_bindings.define_type(privacy, def_trait(def_id), sp);
visit_item(item, new_parent, visitor);
Expand Down Expand Up @@ -1589,7 +1597,15 @@ pub impl Resolver {
interned_method_names.insert(method_name);
}
}
self.trait_info.insert(def_id, interned_method_names);
for interned_method_names.each |name| {
if !self.method_map.contains_key(name) {
self.method_map.insert(*name, HashSet::new());
}
match self.method_map.find_mut(name) {
Some(s) => { s.insert(def_id); },
_ => fail!("Can't happen"),
}
}

child_name_bindings.define_type(Public, def, dummy_sp());
}
Expand Down Expand Up @@ -4935,118 +4951,111 @@ pub impl Resolver {
debug!("(searching for traits containing method) looking for '%s'",
*self.session.str_of(name));


let mut found_traits = ~[];
let mut search_module = self.current_module;
loop {
// Look for the current trait.
match /*bad*/copy self.current_trait_refs {
Some(trait_def_ids) => {
for trait_def_ids.each |trait_def_id| {
self.add_trait_info_if_containing_method(
&mut found_traits, *trait_def_id, name);
}
}
None => {
// Nothing to do.
}
}

// Look for trait children.
for search_module.children.each_value |&child_name_bindings| {
match child_name_bindings.def_for_namespace(TypeNS) {
Some(def) => {
match def {
def_trait(trait_def_id) => {
self.add_trait_info_if_containing_method(
&mut found_traits, trait_def_id, name);
}
_ => {
// Continue.
match self.method_map.find(&name) {
Some(candidate_traits) => loop {
// Look for the current trait.
match /*bad*/copy self.current_trait_refs {
Some(trait_def_ids) => {
for trait_def_ids.each |trait_def_id| {
if candidate_traits.contains(trait_def_id) {
self.add_trait_info(
&mut found_traits,
*trait_def_id, name);
}
}
}
None => {
// Continue.
// Nothing to do.
}
}
}

// Look for imports.
for search_module.import_resolutions.each_value
|&import_resolution| {

match import_resolution.target_for_namespace(TypeNS) {
None => {
// Continue.
}
Some(target) => {
match target.bindings.def_for_namespace(TypeNS) {
Some(def) => {
match def {
def_trait(trait_def_id) => {
let added = self.
add_trait_info_if_containing_method(
// Look for trait children.
for search_module.children.each_value |&child_name_bindings| {
match child_name_bindings.def_for_namespace(TypeNS) {
Some(def) => {
match def {
def_trait(trait_def_id) => {
if candidate_traits.contains(&trait_def_id) {
self.add_trait_info(
&mut found_traits,
trait_def_id, name);
if added {
self.used_imports.insert(
import_resolution.id);
}
}
_ => {
// Continue.
}
}
}
None => {
// Continue.
_ => {
// Continue.
}
}
}
None => {
// Continue.
}
}
}
}

// Move to the next parent.
match search_module.parent_link {
NoParentLink => {
// Done.
break;
// Look for imports.
for search_module.import_resolutions.each_value
|&import_resolution| {

match import_resolution.target_for_namespace(TypeNS) {
None => {
// Continue.
}
Some(target) => {
match target.bindings.def_for_namespace(TypeNS) {
Some(def) => {
match def {
def_trait(trait_def_id) => {
if candidate_traits.contains(&trait_def_id) {
self.add_trait_info(
&mut found_traits,
trait_def_id, name);
self.used_imports.insert(
import_resolution.id);
}
}
_ => {
// Continue.
}
}
}
None => {
// Continue.
}
}
}
}
}
ModuleParentLink(parent_module, _) |
BlockParentLink(parent_module, _) => {
search_module = parent_module;

// Move to the next parent.
match search_module.parent_link {
NoParentLink => {
// Done.
break;
}
ModuleParentLink(parent_module, _) |
BlockParentLink(parent_module, _) => {
search_module = parent_module;
}
}
}
},
_ => ()
}

return found_traits;
}

fn add_trait_info_if_containing_method(&self,
found_traits: &mut ~[def_id],
trait_def_id: def_id,
name: ident)
-> bool {
debug!("(adding trait info if containing method) trying trait %d:%d \
for method '%s'",
fn add_trait_info(&self,
found_traits: &mut ~[def_id],
trait_def_id: def_id,
name: ident) {
debug!("(adding trait info) found trait %d:%d for method '%s'",
trait_def_id.crate,
trait_def_id.node,
*self.session.str_of(name));

match self.trait_info.find(&trait_def_id) {
Some(trait_info) if trait_info.contains(&name) => {
debug!("(adding trait info if containing method) found trait \
%d:%d for method '%s'",
trait_def_id.crate,
trait_def_id.node,
*self.session.str_of(name));
found_traits.push(trait_def_id);
true
}
Some(_) | None => {
false
}
}
found_traits.push(trait_def_id);
}

fn add_fixed_trait_for_expr(@mut self,
Expand Down