Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #18986 from Veykril/push-zlwvwlowpzqm
Goto `Display::fmt` when invoked on `to_string`
Lukas Wirth 2025-01-21
parent 8db3331 · parent a3eee10 · commit 2c040c0
-rw-r--r--crates/hir/src/semantics.rs2
-rw-r--r--crates/ide-db/src/famous_defs.rs7
-rw-r--r--crates/ide/src/goto_definition.rs39
-rw-r--r--crates/intern/src/symbol/symbols.rs1
4 files changed, 49 insertions, 0 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 708db2c08d..09470bed9c 100644
--- a/crates/hir/src/semantics.rs
+++ b/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/crates/ide-db/src/famous_defs.rs b/crates/ide-db/src/famous_defs.rs
index 9b76baf487..2f4d07446f 100644
--- a/crates/ide-db/src/famous_defs.rs
+++ b/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/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index 99d0d6af71..d18732a6b8 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/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/crates/intern/src/symbol/symbols.rs b/crates/intern/src/symbol/symbols.rs
index 0f80891404..7a090a6b6b 100644
--- a/crates/intern/src/symbol/symbols.rs
+++ b/crates/intern/src/symbol/symbols.rs
@@ -461,6 +461,7 @@ define_symbols! {
test,
then,
thiscall,
+ to_string,
trace_macros,
transmute_opts,
transmute_trait,