diff options
| author | Lukas Wirth <lukastw97@gmail.com> | 2025-01-21 09:25:05 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-01-21 09:25:05 +0000 |
| commit | 4308352b42f69d2b1737dc0eceabca5c03f05b15 (patch) | |
| tree | 44f930c9fb2f115a4f095ef4cb3da521007b743c | |
| parent | 4b716bbb4c5a73c42259403447906b521fefc719 (diff) | |
| parent | e9b410d29ce996abc31bd85f8168936f6eeda2aa (diff) | |
| download | rust-4308352b42f69d2b1737dc0eceabca5c03f05b15.tar.gz rust-4308352b42f69d2b1737dc0eceabca5c03f05b15.zip | |
Merge pull request #18986 from Veykril/push-zlwvwlowpzqm
Goto `Display::fmt` when invoked on `to_string`
4 files changed, 49 insertions, 0 deletions
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 708db2c08dd..09470bed9cf 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -1483,6 +1483,8 @@ impl<'db> SemanticsImpl<'db> { self.analyze(try_expr.syntax())?.resolve_try_expr(self.db, try_expr) } + // This does not resolve the method call to the correct trait impl! + // We should probably fix that. pub fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> { self.analyze(call.syntax())?.resolve_method_call_as_callable(self.db, call) } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs index 9b76baf4872..2f4d07446f2 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs @@ -142,6 +142,13 @@ impl FamousDefs<'_, '_> { self.find_macro("core:unimplemented") } + pub fn core_fmt_Display(&self) -> Option<Trait> { + self.find_trait("core:fmt:Display") + } + + pub fn alloc_string_ToString(&self) -> Option<Trait> { + self.find_trait("alloc:string:ToString") + } pub fn builtin_crates(&self) -> impl Iterator<Item = Crate> { IntoIterator::into_iter([ self.std(), 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 99d0d6af716..d18732a6b84 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs @@ -185,6 +185,15 @@ fn find_definition_for_known_blanket_dual_impls( // Extract the `T` from `Result<T, ..>` [return_type.type_arguments().next()?, callable.receiver_param(sema.db)?.1], )? + } else if fn_name == sym::to_string && fd.alloc_string_ToString() == Some(t) { + let dual = fd.core_fmt_Display()?; + let dual_f = dual.function(sema.db, &sym::fmt)?; + sema.resolve_trait_impl_method( + return_type.clone(), + dual, + dual_f, + [callable.receiver_param(sema.db)?.1.strip_reference()], + )? } else { return None; }; @@ -3235,4 +3244,34 @@ fn f() { "#, ); } + + #[test] + fn to_string_call_to_display_definition() { + check( + r#" +//- minicore:fmt +//- /alloc.rs crate:alloc +pub mod string { + pub struct String; + pub trait ToString { + fn to_string(&self) -> String; + } + + impl<T: core::fmt::Display> ToString for T { + fn to_string(&self) -> String { String } + } +} +//- /lib.rs crate:lib deps:alloc +use alloc::string::ToString; +struct A; +impl core::fmt::Display for A { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {} + // ^^^ +} +fn f() { + A.to_string$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 0f80891404e..7a090a6b6bb 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -461,6 +461,7 @@ define_symbols! { test, then, thiscall, + to_string, trace_macros, transmute_opts, transmute_trait, |
