Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/goto_definition.rs')
-rw-r--r--crates/ide/src/goto_definition.rs55
1 files changed, 4 insertions, 51 deletions
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index 112faa7a65..905376e755 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -5,11 +5,10 @@ use crate::{
navigation_target::{self, ToNav},
FilePosition, NavigationTarget, RangeInfo, TryToNav, UpmappingResult,
};
-use hir::{AsAssocItem, AssocItem, FileRange, Impl, InFile, MacroFileIdExt, ModuleDef, Semantics};
+use hir::{AsAssocItem, AssocItem, FileRange, InFile, MacroFileIdExt, ModuleDef, Semantics};
use ide_db::{
base_db::{AnchoredPath, FileLoader, SourceDatabase},
defs::{Definition, IdentClass},
- famous_defs::FamousDefs,
helpers::pick_best_token,
RootDatabase, SymbolKind,
};
@@ -82,8 +81,7 @@ pub(crate) fn goto_definition(
return Some(RangeInfo::new(original_token.text_range(), navs));
}
- if let Some(navs) = find_definition_for_known_blanket_dual_impls(sema, file_id, &original_token)
- {
+ if let Some(navs) = find_definition_for_known_blanket_dual_impls(sema, &original_token) {
return Some(RangeInfo::new(original_token.text_range(), navs));
}
@@ -134,58 +132,13 @@ pub(crate) fn goto_definition(
// If the token is into(), try_into(), parse(), search the definition of From, TryFrom, FromStr.
fn find_definition_for_known_blanket_dual_impls(
sema: &Semantics<'_, RootDatabase>,
- file_id: FileId,
original_token: &SyntaxToken,
) -> Option<Vec<NavigationTarget>> {
- let db = sema.db;
- let krate = sema.file_to_module_def(file_id)?.krate();
-
- // e.g. if the method call is let b = a.into(),
- // - receiver_type is A (type of a)
- // - return_type is B (type of b)
- // We will find the definition of B::from(a: A).
let method_call = ast::MethodCallExpr::cast(original_token.parent()?.parent()?)?;
- let callable = sema.resolve_method_call_as_callable(&method_call)?;
- let (_, receiver_type) = callable.receiver_param(db)?;
- let return_type = callable.return_type();
-
- let (search_method, search_trait, return_type) = match method_call.name_ref()?.text().as_str() {
- "into" => ("from", FamousDefs(sema, krate).core_convert_From()?, return_type),
- // If the method is try_into() or parse(), return_type is Result<T, Error>.
- // Get T from type arguments of Result<T, Error>.
- "try_into" => (
- "try_from",
- FamousDefs(sema, krate).core_convert_TryFrom()?,
- return_type.type_arguments().next()?,
- ),
- "parse" => (
- "from_str",
- FamousDefs(sema, krate).core_str_FromStr()?,
- return_type.type_arguments().next()?,
- ),
- _ => return None,
- };
-
- let from_impls = Impl::all_for_type(db, return_type)
- .into_iter()
- .filter(|impl_| impl_.trait_(db).is_some_and(|trait_| trait_ == search_trait));
- let from_methods = from_impls.flat_map(|impl_| impl_.items(db)).filter_map(|item| match item {
- AssocItem::Function(function) if function.name(db).as_str() == search_method => {
- Some(function)
- }
- _ => None,
- });
- let target_method = from_methods.into_iter().find(|method| {
- let args = method.assoc_fn_params(db);
-
- // FIXME: This condition does not work for complicated cases such as
- // receiver_type: Vec<i64>
- // arg.ty(): T: IntoIterator<Item = i64>
- args.first().is_some_and(|arg| receiver_type.could_coerce_to(db, arg.ty()))
- })?;
+ let target_method = sema.resolve_known_blanket_dual_impls(&method_call)?;
let def = Definition::from(target_method);
- Some(def_to_nav(db, def))
+ Some(def_to_nav(sema.db, def))
}
fn try_lookup_include_path(