about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2025-01-20 16:32:17 +0100
committerLukas Wirth <lukastw97@gmail.com>2025-01-20 16:32:17 +0100
commit4bc683dfd2934ed7e9ae055e393f06ecf9115b19 (patch)
treeab3479e1744ca2d30acb0ee6c77befdf66841da1
parent48d17b4181e3ddffad73d5af1377af66b2ddf4f3 (diff)
downloadrust-4bc683dfd2934ed7e9ae055e393f06ecf9115b19.tar.gz
rust-4bc683dfd2934ed7e9ae055e393f06ecf9115b19.zip
Bring back goto def redirect for parse -> FromStr
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_definition.rs46
-rw-r--r--src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs1
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/src/minicore.rs10
5 files changed, 59 insertions, 4 deletions
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 220baeb1520..4938478bb12 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -4682,6 +4682,10 @@ impl Type {
         matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Bool))
     }
 
+    pub fn is_str(&self) -> bool {
+        matches!(self.ty.kind(Interner), TyKind::Str)
+    }
+
     pub fn is_never(&self) -> bool {
         matches!(self.ty.kind(Interner), TyKind::Never)
     }
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index 0b76f2e1121..708db2c08dd 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -1441,7 +1441,7 @@ impl<'db> SemanticsImpl<'db> {
 
     /// Env is used to derive the trait environment
     // FIXME: better api for the trait environment
-    pub fn resolve_impl_method(
+    pub fn resolve_trait_impl_method(
         &self,
         env: Type,
         trait_: Trait,
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 2c6c6e6e6c1..99d0d6af716 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
@@ -141,15 +141,35 @@ fn find_definition_for_known_blanket_dual_impls(
     let method_call = ast::MethodCallExpr::cast(original_token.parent()?.parent()?)?;
     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 assoc = f.as_assoc_item(sema.db)?;
 
     let return_type = callable.return_type();
     let fd = FamousDefs(sema, return_type.krate(sema.db));
+
+    let t = match assoc.container(sema.db) {
+        hir::AssocItemContainer::Trait(t) => t,
+        hir::AssocItemContainer::Impl(impl_)
+            if impl_.self_ty(sema.db).is_str() && f.name(sema.db) == sym::parse =>
+        {
+            let t = fd.core_convert_FromStr()?;
+            let t_f = t.function(sema.db, &sym::from_str)?;
+            return sema
+                .resolve_trait_impl_method(
+                    return_type.clone(),
+                    t,
+                    t_f,
+                    [return_type.type_arguments().next()?],
+                )
+                .map(|f| def_to_nav(sema.db, f.into()));
+        }
+        hir::AssocItemContainer::Impl(_) => return None,
+    };
+
     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(
+        sema.resolve_trait_impl_method(
             return_type.clone(),
             dual,
             dual_f,
@@ -158,7 +178,7 @@ fn find_definition_for_known_blanket_dual_impls(
     } 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(
+        sema.resolve_trait_impl_method(
             return_type.clone(),
             dual,
             dual_f,
@@ -3195,4 +3215,24 @@ 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();
+}
+        "#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
index e7c3668c0fc..59c0c9dca1c 100644
--- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
+++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
@@ -243,6 +243,7 @@ define_symbols! {
     from,
     From,
     FromStr,
+    from_str,
     from_output,
     from_residual,
     from_usize,
diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
index 4a44eaf5d11..fd06736a252 100644
--- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
+++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
@@ -1574,6 +1574,15 @@ pub mod str {
     pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
         ""
     }
+    pub trait FromStr: Sized {
+        type Err;
+        fn from_str(s: &str) -> Result<Self, Self::Err>;
+    }
+    impl str {
+        pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
+            FromStr::from_str(self)
+        }
+    }
 }
 // endregion:str
 
@@ -1848,6 +1857,7 @@ pub mod prelude {
             option::Option::{self, None, Some},      // :option
             panic,                                   // :panic
             result::Result::{self, Err, Ok},         // :result
+            str::FromStr,                            // :str
         };
     }