diff options
| author | Lukas Wirth <lukastw97@gmail.com> | 2025-01-20 16:23:19 +0100 |
|---|---|---|
| committer | Lukas Wirth <lukastw97@gmail.com> | 2025-01-20 16:24:42 +0100 |
| commit | 48d17b4181e3ddffad73d5af1377af66b2ddf4f3 (patch) | |
| tree | 0c35e5abc7a8e9adfb03b6346ce8fa08a5379a74 /src/tools/rust-analyzer/crates/ide | |
| parent | 1eb9d15e42922ad6bfc851b5745c59e9a2f6cfbc (diff) | |
| download | rust-48d17b4181e3ddffad73d5af1377af66b2ddf4f3.tar.gz rust-48d17b4181e3ddffad73d5af1377af66b2ddf4f3.zip | |
Move dual blanket impl logic from source analyzer to goto_def
Diffstat (limited to 'src/tools/rust-analyzer/crates/ide')
| -rw-r--r-- | src/tools/rust-analyzer/crates/ide/src/goto_definition.rs | 67 |
1 files changed, 39 insertions, 28 deletions
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs index f804cc36772..2c6c6e6e6c1 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs @@ -5,10 +5,14 @@ use crate::{ navigation_target::{self, ToNav}, FilePosition, NavigationTarget, RangeInfo, TryToNav, UpmappingResult, }; -use hir::{AsAssocItem, AssocItem, FileRange, InFile, MacroFileIdExt, ModuleDef, Semantics}; +use hir::{ + sym, AsAssocItem, AssocItem, CallableKind, FileRange, HasCrate, InFile, MacroFileIdExt, + ModuleDef, Semantics, +}; use ide_db::{ base_db::{AnchoredPath, FileLoader, SourceDatabase}, defs::{Definition, IdentClass}, + famous_defs::FamousDefs, helpers::pick_best_token, RootDatabase, SymbolKind, }; @@ -129,15 +133,45 @@ pub(crate) fn goto_definition( Some(RangeInfo::new(original_token.text_range(), navs)) } -// If the token is into(), try_into(), parse(), search the definition of From, TryFrom, FromStr. +// If the token is into(), try_into(), search the definition of From, TryFrom. fn find_definition_for_known_blanket_dual_impls( sema: &Semantics<'_, RootDatabase>, original_token: &SyntaxToken, ) -> Option<Vec<NavigationTarget>> { let method_call = ast::MethodCallExpr::cast(original_token.parent()?.parent()?)?; - let target_method = sema.resolve_known_blanket_dual_impls(&method_call)?; - - let def = Definition::from(target_method); + let callable = sema.resolve_method_call_as_callable(&method_call)?; + let CallableKind::Function(f) = callable.kind() else { return None }; + let t = f.as_assoc_item(sema.db)?.container_trait(sema.db)?; + + let return_type = callable.return_type(); + let fd = FamousDefs(sema, return_type.krate(sema.db)); + let fn_name = f.name(sema.db); + let f = if fn_name == sym::into && fd.core_convert_Into() == Some(t) { + let dual = fd.core_convert_From()?; + let dual_f = dual.function(sema.db, &sym::from)?; + sema.resolve_impl_method( + return_type.clone(), + dual, + dual_f, + [return_type, callable.receiver_param(sema.db)?.1], + )? + } else if fn_name == sym::try_into && fd.core_convert_TryInto() == Some(t) { + let dual = fd.core_convert_TryFrom()?; + let dual_f = dual.function(sema.db, &sym::try_from)?; + sema.resolve_impl_method( + return_type.clone(), + dual, + dual_f, + // Extract the `T` from `Result<T, ..>` + [return_type.type_arguments().next()?, callable.receiver_param(sema.db)?.1], + )? + } else { + return None; + }; + // Assert that we got a trait impl function, if we are back in a trait definition we didn't + // succeed + let _t = f.as_assoc_item(sema.db)?.implemented_trait(sema.db)?; + let def = Definition::from(f); Some(def_to_nav(sema.db, def)) } @@ -3161,27 +3195,4 @@ fn f() { "#, ); } - - #[test] - fn parse_call_to_from_str_definition() { - check( - r#" -//- minicore: from, str -struct A; - -impl FromStr for A { - type Error = String; - - fn from_str(value: &str) -> Result<Self, Self::Error> { - //^^^^^^^^ - Ok(A) - } -} - -fn f() { - let a: Result<A, _> = "aaaaaa".parse$0(); -} - "#, - ); - } } |
