From cefb2204cb109529fd9d138d9b21dddd8c30ff3d Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 24 Jun 2020 17:45:38 +0200 Subject: Make `iterate_method_candidates` non-generic --- crates/ra_hir_ty/src/method_resolution.rs | 129 +++++++++++++++++------------- 1 file changed, 73 insertions(+), 56 deletions(-) (limited to 'crates/ra_hir_ty/src') diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index ed638c195..8b59a8bd6 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs @@ -271,6 +271,33 @@ pub fn iterate_method_candidates( mode: LookupMode, mut callback: impl FnMut(&Ty, AssocItemId) -> Option, ) -> Option { + let mut slot = None; + iterate_method_candidates_impl( + ty, + db, + env, + krate, + traits_in_scope, + name, + mode, + &mut |ty, item| { + slot = callback(ty, item); + slot.is_some() + }, + ); + slot +} + +pub fn iterate_method_candidates_impl( + ty: &Canonical, + db: &dyn HirDatabase, + env: Arc, + krate: CrateId, + traits_in_scope: &FxHashSet, + name: Option<&Name>, + mode: LookupMode, + callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, +) -> bool { match mode { LookupMode::MethodCall => { // For method calls, rust first does any number of autoderef, and then one @@ -298,19 +325,19 @@ pub fn iterate_method_candidates( let deref_chain = autoderef_method_receiver(db, krate, ty); for i in 0..deref_chain.len() { - if let Some(result) = iterate_method_candidates_with_autoref( + if iterate_method_candidates_with_autoref( &deref_chain[i..], db, env.clone(), krate, traits_in_scope, name, - &mut callback, + callback, ) { - return Some(result); + return true; } } - None + false } LookupMode::Path => { // No autoderef for path lookups @@ -321,22 +348,22 @@ pub fn iterate_method_candidates( krate, traits_in_scope, name, - &mut callback, + callback, ) } } } -fn iterate_method_candidates_with_autoref( +fn iterate_method_candidates_with_autoref( deref_chain: &[Canonical], db: &dyn HirDatabase, env: Arc, krate: CrateId, traits_in_scope: &FxHashSet, name: Option<&Name>, - mut callback: impl FnMut(&Ty, AssocItemId) -> Option, -) -> Option { - if let Some(result) = iterate_method_candidates_by_receiver( + mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, +) -> bool { + if iterate_method_candidates_by_receiver( &deref_chain[0], &deref_chain[1..], db, @@ -346,13 +373,13 @@ fn iterate_method_candidates_with_autoref( name, &mut callback, ) { - return Some(result); + return true; } let refed = Canonical { num_vars: deref_chain[0].num_vars, value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()), }; - if let Some(result) = iterate_method_candidates_by_receiver( + if iterate_method_candidates_by_receiver( &refed, deref_chain, db, @@ -362,13 +389,13 @@ fn iterate_method_candidates_with_autoref( name, &mut callback, ) { - return Some(result); + return true; } let ref_muted = Canonical { num_vars: deref_chain[0].num_vars, value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()), }; - if let Some(result) = iterate_method_candidates_by_receiver( + if iterate_method_candidates_by_receiver( &ref_muted, deref_chain, db, @@ -378,12 +405,12 @@ fn iterate_method_candidates_with_autoref( name, &mut callback, ) { - return Some(result); + return true; } - None + false } -fn iterate_method_candidates_by_receiver( +fn iterate_method_candidates_by_receiver( receiver_ty: &Canonical, rest_of_deref_chain: &[Canonical], db: &dyn HirDatabase, @@ -391,20 +418,18 @@ fn iterate_method_candidates_by_receiver( krate: CrateId, traits_in_scope: &FxHashSet, name: Option<&Name>, - mut callback: impl FnMut(&Ty, AssocItemId) -> Option, -) -> Option { + mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, +) -> bool { // We're looking for methods with *receiver* type receiver_ty. These could // be found in any of the derefs of receiver_ty, so we have to go through // that. for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) { - if let Some(result) = - iterate_inherent_methods(self_ty, db, name, Some(receiver_ty), krate, &mut callback) - { - return Some(result); + if iterate_inherent_methods(self_ty, db, name, Some(receiver_ty), krate, &mut callback) { + return true; } } for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) { - if let Some(result) = iterate_trait_method_candidates( + if iterate_trait_method_candidates( self_ty, db, env.clone(), @@ -414,40 +439,28 @@ fn iterate_method_candidates_by_receiver( Some(receiver_ty), &mut callback, ) { - return Some(result); + return true; } } - None + false } -fn iterate_method_candidates_for_self_ty( +fn iterate_method_candidates_for_self_ty( self_ty: &Canonical, db: &dyn HirDatabase, env: Arc, krate: CrateId, traits_in_scope: &FxHashSet, name: Option<&Name>, - mut callback: impl FnMut(&Ty, AssocItemId) -> Option, -) -> Option { - if let Some(result) = iterate_inherent_methods(self_ty, db, name, None, krate, &mut callback) { - return Some(result); - } - if let Some(result) = iterate_trait_method_candidates( - self_ty, - db, - env, - krate, - traits_in_scope, - name, - None, - &mut callback, - ) { - return Some(result); + mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, +) -> bool { + if iterate_inherent_methods(self_ty, db, name, None, krate, &mut callback) { + return true; } - None + iterate_trait_method_candidates(self_ty, db, env, krate, traits_in_scope, name, None, callback) } -fn iterate_trait_method_candidates( +fn iterate_trait_method_candidates( self_ty: &Canonical, db: &dyn HirDatabase, env: Arc, @@ -455,8 +468,8 @@ fn iterate_trait_method_candidates( traits_in_scope: &FxHashSet, name: Option<&Name>, receiver_ty: Option<&Canonical>, - mut callback: impl FnMut(&Ty, AssocItemId) -> Option, -) -> Option { + callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, +) -> bool { // if ty is `dyn Trait`, the trait doesn't need to be in scope let inherent_trait = self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t)); @@ -489,23 +502,27 @@ fn iterate_trait_method_candidates( } } known_implemented = true; - if let Some(result) = callback(&self_ty.value, *item) { - return Some(result); + if callback(&self_ty.value, *item) { + return true; } } } - None + false } -fn iterate_inherent_methods( +fn iterate_inherent_methods( self_ty: &Canonical, db: &dyn HirDatabase, name: Option<&Name>, receiver_ty: Option<&Canonical>, krate: CrateId, - mut callback: impl FnMut(&Ty, AssocItemId) -> Option, -) -> Option { - for krate in self_ty.value.def_crates(db, krate)? { + callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, +) -> bool { + let def_crates = match self_ty.value.def_crates(db, krate) { + Some(k) => k, + None => return false, + }; + for krate in def_crates { let impls = db.impls_in_crate(krate); for impl_def in impls.lookup_impl_defs(&self_ty.value) { @@ -521,13 +538,13 @@ fn iterate_inherent_methods( test_utils::mark::hit!(impl_self_type_match_without_receiver); continue; } - if let Some(result) = callback(&self_ty.value, item) { - return Some(result); + if callback(&self_ty.value, item) { + return true; } } } } - None + false } /// Returns the self type for the index trait call. -- cgit v1.2.3